[04.15/week05]TIL

CHO WanGi·2025년 4월 15일

KRAFTON JUNGLE 8th

목록 보기
29/89

오늘 한줄 요약

쉽지 않다.

오늘 새롭게 배운 것

  • C언어 동적 메모리 할당, 메인함수 인자
  • BST 노드 삭제
  • 배열 원소 접근 방법(배열방식과 포인터 방식)

C언어

동적 메모리 할당

  • 이게 왜 필요한가?
    사용자 입력을 받는 등, 배열의 크기가 정해지지 않았을 때 동적 메모리 할당을 통해 RunTime에 메모리를 할당할 수 있기 때문

  • 어떻게 쓰는가?

#include<stdlib.h>

arr = (int *)malloc(sizeof(int)*SizeOfArray)

이렇게 선언하게 되면 int arr[SizeOfArray] 와 동일한 크기를 갖게 된다.

🚨 malloc으로 할당했다면 free(arr) 로 다시 돌려주자

2차원 배열 동적 할당
  1. 포인터 배열을 통해 배열의 각 원소가 포인터인 배열
  2. 진짜 메모리상 존재하는 2차원 배열로 만들기

두가지 방법중 후자가 더 빠르다.
왜, malloc은 상당히 느린 함수인데, 포인터 배열같은 경우 height 만큼 Malloc을 호출하기 때문에 느리다.

메인함수 인자 argc, argv

  • 이 인자는 어디서 오는가?
    OS가 넣어주는 것으로 argc는 메인 함수가 받은 인자의 개수를, argv는 main 함수가 받은 각자의 인자들을 의미

  • EX.

$ ./hello world test
  • argc == 3 (총 3개의 인자: ./hello, "world", "test")
  • argv[0] == "./hello"
  • argv[1] == "world"
  • argv[2] == "test"

가 되고, 이를 메모리상 보면

argv
 |
 v
+---------+---------+---------+
| argv[0] | argv[1] | argv[2] |
+---------+---------+---------+
    |         |         |
    v         v         v
"./hello"  "world"   "test"

BST 노드 삭제 방법

  • Case
  1. 리프 노드 (자식 없음) → 그냥 제거
  2. 자식 1개 → 자식과 부모를 직접 연결
  3. 자식 2개 → 전임자(Predecessor) 또는 후임자(Successor)로 대체
  • 자식이 2개인 경우

✅ 1. 전임자(Predecessor) 방식
📌 정의:
전임자 = 왼쪽 서브트리의 가장 큰 값

🔁 삭제 과정:
왼쪽 서브트리로 이동
→ 루트를 기준으로 오른쪽으로 계속 이동하여 가장 큰 노드 찾기
삭제 대상 노드의 값 ↔ 전임자 값 교환
전임자 노드 삭제

전임자는 항상 자식이 0개 또는 1개이므로 일반 삭제 가능


✅ 2. 후임자(Successor) 방식
📌 정의:
후임자 = 오른쪽 서브트리의 가장 작은 값

🔁 삭제 과정:
오른쪽 서브트리로 이동
→ 루트를 기준으로 왼쪽으로 계속 이동하여 가장 작은 노드 찾기

삭제 대상 노드의 값 ↔ 후임자 값 교환

후임자 노드 삭제


배열 원소 접근 방법(배열방식과 포인터 방식)

프로그래밍 언어 C에서 배열은 내부적으로 포인터처럼 작동.
즉, 배열의 이름 자체가 배열의 첫 번째 원소의 주소로 해석,
이를 통해 두 가지 방식으로 배열 원소에 접근 가능

  • 배열 방식 (arr[i])
  • 포인터 방식 (*(arr + i))

    1. 배열 방식: arr[i]

가장 익숙한 방식입니다.
배열의 i번째 요소에 직접 접근합니다.

int arr[3] = {10, 20, 30};
printf("%d\n", arr[1]);  // 출력: 20

    1. 포인터 방식: *(arr + i)

배열 이름 arr은 내부적으로 &arr[0]와 동일한 주소입니다.
이 주소에 i를 더해 i번째 원소의 주소를 구한 후, 그 값을 역참조(*)하여 접근합니다.

int arr[3] = {10, 20, 30};
printf("%d\n", *(arr + 1));  // 출력: 20

  • 실제 메모리 예시
int arr[3] = {10, 20, 30};
주소      값
0x100   10   ← arr[0] == *arr
0x104   20   ← arr[1] == *(arr + 1)
0x108   30   ← arr[2] == *(arr + 2)

공부하다가 아쉬운 점

문제를 풀고있는데, 이게 직접 구현한다기 보단 해당 자료구조를 이해하고
밑에 제시된 메서드를 사용해서 특정 함수를 구현하다보니 뭔가 제대로 이해하는게 맞나 싶다...

profile
제 Velog에 오신 모든 분들이 작더라도 인사이트를 얻어가셨으면 좋겠습니다 :)

0개의 댓글