알고리즘 주간이 끝나고 C로 Red-Black Tree를 구현해야 하는 과제가 찾아왔다.
공지사항에서 지시한 대로 Ubuntu 환경에 외부 github의 repository에 올라왔던 파일들을 복제하고, 이를 나의 repository 에 push 하는 것 까지는 성공했지만 이 파일 구조들이 대체 뭔지 알 수가 없었다.
rbtree.c 안에 read.me에서 요구하는 여러 기능들을 함수를 통해 직접 구현해야 한다는 것 까진 알겠는데..
rbtree.h는 또 뭐고, makefile은 뭐길래 같은 이름의 파일이 3개나 있는지 알고 싶었다.
우선 어쩌고.h 파일은 생각보다 익숙한 녀석이었다.
C 코드 예제에 백이면 백 등장하는
#include <stdio.h>
가 바로 대표적인 .h파일, 헤더 파일이었다.
헤더파일의 역할은 c로 짠 코드 내부가 너무 복잡해지지 않도록 다른 파일에 함수나 다른 데이터 타입들을 미리 선언해두는 역할을 하는거다...정도로 이해했다.
실제로 우리에게 주어진 rbtree.c 코드 내에는 rbtree 타입이나 node_t 타입에 대한 어떤 정의도 없음에도 불구하고 rbtree.h 내에서 이러한 구조체에 대해서 typedef를 미리 시행했기 때문에 문제가 없었던 것이다.
내가 알고 있는 지식에 비유하자면, HTML의 index.html 내의 <script>
태그 내부에 같은 디렉토리 내의 index.js파일을 참조하라고 써놓고, 실제 JS 코드는 index.js 같은 파일 내에 써놓는 것 같은 느낌이었다.
참고로 이러한 header 파일들은 어쩌고.c 코드 상단에 #include 라는 코드를 통해서 링커가 .c 파일과 .h 파일을 묶어서 해석하게 된다고 한다. <stdio.h> 같은 C언어 내부에 이미 존재하는 헤더 파일은 <> 꺾쇠를 통해서 불러올 수 있지만, 코딩하는 과정중에 직접 만든 헤더 파일을 불러오려면 ""큰 따옴표로 묶어야 한다.
Makefile은 아직 뭔지 확실하게 모르겠지만 gcc를 통해 작성한 .c파일을 실행할 때 여러개의 실행해야 할 파일이 있을 때 이걸 일일히 한줄씩 쓰면 번거롭기 때문에 한번에 묶어서 실행하는 방법...정도는 이해했다.
그럼 rbtree.h 파일에 대체 뭔 소리를 써 놓은건지 정리를 한 번 해봤다.
typedef enum { RBTREE_RED, RBTREE_BLACK } color_t;
= 기호화된 정수 RBTREE_RED와 RBTREE_BLACK 을 멤버로 갖는 열거형 의 데이터 타입을 colot_t 로 재정의한다.
typedef int key_t;
= 마찬가지로 int 타입 데이터를 key_t로 재정의한다.
typedef struct node_t {
color_t color;
key_t key;
struct node_t *parent, *left, *right;
} node_t;
= color_t 타입의 변수 color
, key_t 타입의 변수 key
, 구조체 node_t 타입 변수 *parent
, *left
, *rignt
를 멤버로 갖는 구조체 node_t의 데이터 타입을 node_t로 재정의 하겠다.
= 다시말해 어떤 노드에 색깔정보, key 정보, 노드의 부모, 왼쪽, 오른쪽 노드의 주소 정보를 담겠다는 말이라고 이해했다.
typedef struct {
node_t *root;
node_t *nil; // for sentinel
} rbtree;
= 멤버로 (앞서 재정의한) node_t 타입의 *root
, node_t 타입의 *nil
을 갖는 구조체를 rbtree라는 타입으로 재정의 하겠다.
이 이후에는 rbtree.c에서 사용되는 함수들의 원형이 적혀있었다. 이렇게 함수의 원형 역시 헤더 파일 내에 정리해두는 것 역시 일반적이라고 한다. 함수를 한 번 선언해두면 여타 다른 파일에서 헤더파일만 불러오면 그 함수를 그대로 사용할 수 있기 때문이고, 만약 어떤 함수에 문제가 발생했을 때 수정하기도 편해지기 때문이다. 50가지 c코드에 같은 내용의 함수를 복사 붙여넣기 했다면 수정 역시 50번을 해야 할 테니까..
이렇게 rbtree.h 파일 내에서 여러 데이터 타입과 함수를 선언하고 재정의했기 때문에 rbtree.c내에서 딱히 뭘 하지 않아도 이러한 데이터 타입들과 함수들을 사용할 수 있는 것이다.