이번 주차때 rbtree코드를 스스로 짜지 않았다. 알고리즘 책에 있는 의사 코드를 그대로 옮기고 해석하기만 했다.
그래서 마지막 날인 오늘 rbtree 코드를 짜면서 신경쓰지 못 했던 부분에 대해 정리하고 이번 주를 마무리하려고 한다.
노드를 calloc으로 할당할 때의 이점?
typedef struct node_t {
color_t color;
key_t key;
struct node_t *parent, *left, *right;
} node_t;
typedef struct {
node_t *root;
node_t *nil; // for sentinel
} rbtree;
rbtree 구조체와
rbtree의 노드에 해당하는 node_t 구조체가 주어진다.
rbtree *new_rbtree(void) {
// TODO: initialize struct if needed
rbtree *p = (rbtree *)calloc(1, sizeof(rbtree));
node_t* nil = (node_t*)calloc(1, sizeof(node_t));
nil->color = RBTREE_BLACK;
p->nil = nil;
p->root = nil;
return p;
}
new_rbtree()함수는 새로운 rbtree 그래프를 하나 생성하는 역할을 한다.
rbtree를 하나 생성하고 그 트리의 root가 nil노드를 가리키게 해서
아직 아무 노드도 가지고 있지 않은 빈 rbtree를 생성해야 한다.
그래서 트리를 생성할 때 해야 할 작업은 해당 트리의 모든 leaf, root 노드가 가리킬 nil노드를 만드는 작업이다.

nil노드도 node_t 타입으로 선언하는데, color값만 할당해주고 key, parent, left, right는 할당하지 않은 채로 사용했다.
사실 나머지 값은 할당해주지 않아도 상관 없나? 하는 의문을 가지고 있었는데 컴파일과 테스트에 문제가 없어서 깊게 공부하지 않고 넘어갔다.
오늘 우리 조원의 calloc에 대한 발표를 듣고 다시 생각해보니 구조체 변수를 calloc으로 할당해줬으므로 할당된 공간이 모두 0으로 초기화되어서 값을 설정해주지 않아도 됐었던 것이 아닐까 예상했다.
calloc으로 구조체를 할당하면 구조체 내부의 모든 필드가 0으로 초기화되고 포인터 변수가 가리키는 곳도 모두 0으로 초기화된다.
참고로 전부 0으로 채워진 부분은 OS에서 '유효하지 않은 주소' 즉 NULL로 해석되기 때문에 calloc으로 포인터를 할당하면 NULL포인터가 된다.
반면 malloc을 사용해 할당한 구조체는 직접 필드값을 초기화해주지 않으면 쓰레기값이 할당된다.
따라서 포인터들이 NULL도 아닌 이상한 부분을 가리키고 있게 되어서 해당 포인터를 사용하면 segfault가 발생하고 메모리 손상 위험이 있다.
결론은 모든 필드를 명시적으로 초기화하는 게 유지보수에 좋지만!
calloc을 쓰면 자동으로 필드들을 0으로 채워주므로 편하고 실수도 줄여준다.
특히나 포인터 타입 변수도 NULL포인터로 만들어주므로 segfault 위험을 줄일 수 있다.
'정글 > 알고리즘' 카테고리의 다른 글
| 링커 (0) | 2025.04.25 |
|---|---|
| AVL Tree (2) | 2025.04.22 |
| Data-Structures Binary Search Tree Q1 - Level Order Traversal 풀이 (2) | 2025.04.16 |
| [백준/Java] 11049번 : 행렬 곱셈 (0) | 2025.04.10 |
| [백준/Java] 9084번 : 동전 (3) | 2025.04.09 |