Data Structure - jjin-choi/study_note GitHub Wiki

ยง Linked List

1. Intro

// Linked List node
typedef struct _node
{
    int data;
    struct _node *next;
} NODE;

// global variable. ์ „์ฒด Linked List์˜ head 
NODE *head; // node pointer
// insert front function
void insert_data(int data)
{
    NODE *temp;
    temp = (NODE*)malloc(sizeof(NODE));
    temp->data = data;
    temp->next = head;
    head = temp;
}

2. Display function

void display(void)
{
    NODE *temp;
    system("clear");
    printf("head");
    // until temp is NULL
    for (temp=head;temp;temp=temp->next)
        printf("->[%d]", temp->data);
    printf("\n");
    getchar();
}

3. Generalized insert function

- Drawback
    1) front insert ๋งŒ ๊ฐ€๋Šฅ ํ˜น์€ ๋งจ ์•ž ์‚ฝ์ž…๊ณผ ๊ทธ๋ ‡์ง€ ์•Š์„ ๋•Œ ์ฝ”๋“œ๊ฐ€ ๋‹ฌ๋ผ์ง 
    2) process ์— 1๊ฐœ๋งŒ ์กด์žฌํ•  ์ˆ˜ ์žˆ์Œ
       insert function ์—์„œ head๊ฐ€ hard coding ๋˜์–ด์žˆ์Œ. 

- Solution
    1) NODE *head ๋ฅผ NODE head ๋กœ ๋ณ€๊ฒฝํ•˜๊ธฐ
       NODE pointer ์—์„œ NODE ๋กœ ๋ณ€๊ฒฝํ•˜์—ฌ ์ค‘๊ฐ„์— node๋ฅผ ์‚ฝ์ž…ํ•  ๊ฒฝ์šฐ๋ฅผ ๋Œ€๋น„ํ•˜์—ฌ code ์ผ๋ฐ˜ํ™”
    2) insert function ์ธ์ž์— NODE pointer ์ถ”๊ฐ€
       ์—ฌ๋Ÿฌ head๊ฐ€ ์กด์žฌํ•  ์ˆ˜ ์žˆ๋„๋ก ์ง€์—ญ ๋ณ€์ˆ˜๋กœ ์„ค์ •ํ•  ๋•Œ์—๋Š” ๋ฐ˜๋“œ์‹œ `์ดˆ๊ธฐํ™”` ํ•ด์ฃผ์–ด์•ผ ํ•จ
       ex) NODE head = {0, };

4. Memory dependency

- Drawback
    1) insert_data ์—์„œ malloc์„ ์‚ฌ์šฉํ•˜๋ฉด heap ์— ์žก์œผ๋ผ๊ณ  ๊ฐ•์š”ํ•˜๋Š” code

- Solution
    1) memory ํ• ๋‹น/ํ•ด์ง€๋ฅผ user์—๊ฒŒ ์œ„์ž„. NODE๋กœ ๋ฐฐ์—ด ์„ ์–ธํ•˜์—ฌ stack์— ํ• ๋‹นํ•ด๋‘”๋‹ค.
       (`memory pooling`: ๋ฏธ๋ฆฌ memory๋ฅผ ์žก์•„๋‘ ์œผ๋กœ์จ ์†๋„ ๊ฐœ์„ , ๋‹จ memory size๊ฐ€ ์ •ํ•ด์ง.
        ํ•˜์ง€๋งŒ ํ˜„์‹ค ์„ธ๊ณ„์—์„œ๋Š” ๋ฉ”๋ชจ๋ฆฌ limit์ด ์กด์žฌํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๊ทธ์— ๋งž๊ฒŒ memory๋ฅผ pooling ํ•ด๋‘๋ฉด ๋จ.)  

โ€ป Stack vs. Heap Memory ์˜์—ญ (code/data/stack/heap)

  • code: code, function, control statement
  • data: global variable, static
  • heap: dynamic (malloc, new) ์†๋„๊ฐ€ ๋งค์šฐ ๋Š๋ฆผ!
  • stack: (temp) local variable, parameter (๋งค๊ฐœ๋ณ€์ˆ˜), return

memory
Link: Memory_Segment

  1 #include <stdio.h> 
  2 #include <stdlib.h>
  3  
  4 typedef struct _node
  5 {
  6     int data;
  7     struct _node *next;
  8 } NODE;
  9  
 10 void insert_data(NODE *temp, NODE *head)
 11 {
 12     temp->next = head->next;
 13     head->next = temp;
 14 }
 15  
 16 void display(NODE *head)
 17 {
 18     NODE *temp;
 19     printf("[HEAD]");
 20     for(temp=head->next;temp;temp=temp->next)
 21         printf("->[%d]", temp->data);
 22     printf("\n");
 23 }
 24  
 25 int main()
 26 {
 27     int i;
 28     NODE head = {0, };
 29     NODE temps[7];
 30  
 31     for(i=0;i<7;i++)
 32     {
 33         temps[i].data = i+1;
 34         display(&head);
 35         insert_data(temps+i, &head);
 36         getchar();
 37     }
 38     return 0;
 39 }

5. Tail node

- Drawback
    1) display function ํ˜น์€ loop ์—์„œ temp๋กœ ์ธํ•ด NULL์„ ์—ญ์ฐธ์กฐํ•˜๊ฒŒ ๋  ๊ฒฝ์šฐ 
       temp->data // ((*temp).data) ์™€ ๋™์ผ
       process๊ฐ€ ๋ฐ”๋กœ ์ฃฝ๊ฒŒ ๋œ๋‹ค. (๋งค์šฐ ์œ„ํ—˜ํ•œ code!) 

- Solution
    1) NULL ์ฐธ์กฐ์˜ ์œ„ํ—˜์„ฑ์„ ๋ฐฐ์ œํ•˜๊ธฐ ์œ„ํ•ด dummy tail node๋ฅผ ๋„์ž…ํ•˜์ž ! 
       ๋งจ ์ฒ˜์Œ์— head์™€ tail์„ ๋งŒ๋“ค๊ณ , tail ์ž์ฒด๊ฐ€ ์ž๊ธฐ ์ž์‹ ์„ ๊ฐ€๋ฆฌํ‚ค๋„๋ก ์ดˆ๊ธฐํ™” ํ•œ๋‹ค. 
  1 #include <stdio.h> 
  2 #include <stdlib.h>
  3  
  4 typedef struct _node
  5 {
  6     int data;
  7     struct _node *next;
  8 } NODE;
  9  
 10 void insert_data(NODE *temp, NODE *head)
 11 {
 12     temp->next = head->next;
 13     head->next = temp;
 14 }
 15  
 16 void display(NODE *head, NODE *tail)
 17 {
 18     NODE *temp;
 19     printf("[HEAD]");
 20     for(temp=head->next;temp!=tail;temp=temp->next) // check temp NODE 
 21         printf("->[%d]", temp->data);
 22     printf("->[TAIL]\n");
 23     getchar();
 24 }
 25  
 26 int main()
 27 {
 28     int i;
 29     NODE tail = {0, &tail};  // tail NODE 
 30     NODE head = {0, &tail};  
 31     NODE temps[7];
 32  
 33     for(i=0;i<7;i++)
 34     {
 35         temps[i].data = i+1;
 36         display(&head, &tail);
 37         insert_data(temps+i, &head);
 38     }
 39     return 0;
 40 }

6. Circular Linked List

- Drawback
    1) ๊ณผ์—ฐ tail์ด ํ•„์š”ํ•œ๊ฐ€? NODE์˜ ํฌ๊ธฐ๊ฐ€ ์ปค์ง€๋ฉด tail ๋•Œ๋ฌธ์— memory ๋‚ญ๋น„ ๋ฐœ์ƒํ•˜๊ฒŒ ๋œ๋‹ค. 
       tail์ด ์—†์–ด๋„ tail๊ณผ ๋™์ผํ•œ ์—ญํ• ์„ ํ•˜๋„๋ก head์—๊ฒŒ tail ์—ญํ•  ๋ถ€์—ฌ (tail์„ ์—†์• ๊ธฐ ์œ„ํ•ด circular ๋„์ž…) 

- Solution
    1) ๋งจ ์ฒ˜์Œ์— head์„ ๋งŒ๋“ค๊ณ , head ์ž์ฒด๊ฐ€ ์ž๊ธฐ ์ž์‹ ์„ ๊ฐ€๋ฆฌํ‚ค๋„๋ก ์ดˆ๊ธฐํ™” ํ•œ๋‹ค. 
 16 void display(NODE *head)
 17 {
 18     NODE *temp;
 19     printf("[HEAD]");
 20     for(temp=head->next;temp!=head;temp=temp->next)
 21         printf("->[%d]", temp->data);
 22     printf("->[HEAD]\n");
 23     getchar();
 24 }
 25  

 26 int main()
 27 {
 28     int i;
 29     NODE head = {0, &head};
 30     NODE temps[7];
 31  
 32     for(i=0;i<7;i++)
 33     {
 34         temps[i].data = i+1;
 35         display(&head);
 36         insert_data(temps+i, &head);
 37     }
 38     return 0;
 39 }

7. reserve function

- Drawback
    1) singular linked list ์˜ ํ•œ๊ณ„์  (reverse ๋ฐฉํ–ฅ)   

- Solution
    1) linked list๋ฅผ reverse ํ•˜๋Š” function ์„ ๋งŒ๋“ค์ž !  
##### ๋‹ค์‹œ ํ•ด๋ณด๊ธฐ !! 
 26 void reverse(NODE *head)
 27 {
 28     NODE *prev = head;
 29     NODE *curr = prev->next;
 30     NODE *next;
 31    
 32     while(curr != head)
 33     {
 34         next = curr->next;
 35         curr->next = prev;
 36  
 37         prev = curr;
 38         curr = next;
 39     }
 40     curr->next = prev;
 41 }

8. Double Linked List

  1 #include <stdio.h>                                                                                                                                                                                            
  2  
  3 typedef struct _node
  4 {
  5     int data;
  6     struct _node *prev;
  7     struct _node *next;
  8 } NODE;
  9  
 10 NODE node;
 11  
 12 void __insert_data(NODE *prev, NODE *temp, NODE *next)
 13 {
 14     temp->next = next;
 15     next->prev = temp;
 16     temp->prev = prev;
 17     prev->next = temp;
 18 }
 19  
 20 void insert_front(NODE *temp, NODE *head)
 21 {
 22     __insert_data(head, temp, head->next);
 23 }
 24  
 25 void insert_back(NODE *temp, NODE *head)
 26 {
 27     __insert_data(head->prev, temp, head);
 28 }

9. Type dependency (void pointer)

  3 typedef struct _node
  4 {
  5     void *data;
  6     struct _node *prev;
  7     struct _node *next;
  8 } NODE;
  9  
 10 NODE node;
 11  
 12 typedef struct
 13 {
 14     char name[20];
 15 } EMPLOYEE;

// loose coupling ์˜ ๋ฌธ์ œ์ 
// node๊ฐ€ ๋จผ์ € ์—†์–ด์ง€๊ฑฐ๋‚˜ (dangling pointer) data๊ฐ€ ๊ฐ€๋ฆฌํ‚ค๋Š” ์ •๋ณด๊ฐ€ ๋จผ์ € ์—†์–ด์ง€๊ฒŒ (null ์ฐธ์กฐ) ๋  ๊ฒฝ์šฐ
// ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ node์™€ data์˜ ํ• ๋‹น๊ณผ ํ•ด์ง€ ์‹œ์ ์„ ํ•ญ์ƒ ์ผ์น˜ ์‹œ์ผœ์•ผ ํ•œ๋‹ค. 

โ€ป loose coupling : Loose coupling is an approach to interconnecting the components in a system or network so that those components, also called elements, depend on each other to the least extent practicable. Coupling refers to the degree of direct knowledge that one element has of another.

Pros: The benefit is that it's much easier to swap other pieces of code/modules/objects/components when the pieces aren't dependent on one another.

Cons: Dangling pointers arise during object destruction, when an object that has an incoming reference is deleted or deallocated, without modifying the value of the pointer, so that the pointer still points to the memory location of the deallocated memory.

10. Type dependency (sizeof)

node์— data๋ฅผ ๋„ฃ์ง€ ๋ง๊ณ , data์— node๋ฅผ ๋„ฃ์–ด๋ผ ! 
๊ทธ๋ฆฌํ•˜๋ฉด type dependency ๋„ ์—†์• ๊ณ  memory ๋™๊ธฐํ™” ๋ฌธ์ œ๋„ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ์ด๋‹ค ~ 

data์˜ node (prev pointer, next pointer) ๋“ค์€ ์„œ๋กœ์˜ node๋“ค์„ ๊ฐ€๋ฆฌํ‚จ๋‹ค. 
์ฆ‰, node๊ฐ€ data๋ฅผ ๊ฐ€๋ฆฌํ‚จ ๊ฒŒ ์•„๋‹ˆ๋ผ node ์ž์ฒด๋ฅผ ๊ฐ€๋ฆฌํ‚ค๊ธฐ ๋•Œ๋ฌธ์— data ์˜์กด์„ฑ๋„ ์—†์–ด์ง€๊ณ  
data๋ฅผ ์—†์•จ ๋•Œ data๋ฅผ ์—†์•จ ๋•Œ, node๋„ ๊ฐ™์ด ์—†์–ด์ง€๊ธฐ ๋•Œ๋ฌธ์— memory ๋™๊ธฐํ™”๋„ ์—†์–ด์ง„๋‹ค. 
  4 typedef struct _node
  5 {
  6     struct _node *prev;
  7     struct _node *next;
  8 } NODE;
  9  
 10 NODE node;
 11  
 12 typedef struct 
 13 {
 14     char name[20]; // padding -> maybe 8 byte * x
 15     NODE list;
 16 } EMPLOYEE;
 17  

 37 void display(NODE *head)
 38 {
 39     EMPLOYEE *emp;
 40     NODE *temp;
 41  
 42     printf ("[HEAD]");
 43     for (temp=head->next; temp != head; temp=temp->next) 
 44     {
 45         emp = (EMPLOYEE*)((char*)temp - (sizeof(EMPLOYEE) - sizeof(NODE)));
 46         printf ("<->[%s]", emp);
 47     }
 48     printf("<->[HEAD]\n");
 49 }
 50  
 51 int main()
 52 {
 53     NODE head = {&head, &head}; // dummy head 
 54     EMPLOYEE emp[M] = { {"TEST1"}, {"TEST2"}, {"TEST3"} };
 55  
 56     int i;
 57  
 58     for (i=0;i<M;i++)
 59     {
 60         insert_back( &emp[i].list, &head );
 61         display(&head);
 62     }
 63  
 64     return 0;
 65 }   

11. Type dependency (container_of)

sizeof ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด 1๊ฐœ์˜ node์— 1๊ฐœ์˜ list๋งŒ ๊ฐ€์งˆ ์ˆ˜ ์žˆ๋‹ค. 
โ€ป pointer ๋ฅผ ์ˆซ์ž๋กœ ๋ณ€๊ฒฝํ•˜๊ณ  ์‹ถ์œผ๋ฉด int ๊ฐ€ ์•„๋‹Œ unsigned long ์„ ์‚ฌ์šฉ ํ•ด์•ผ ํ•œ๋‹ค ! (32bit 64bit ์—์„œ๋„ ํ˜ธํ™˜ ๊ฐ€๋Šฅ)
 12 typedef struct
 13 {    
 14     char name[20];
 15     NODE list1;
 16     NODE list2;
 17      
 18 } EMPLOYEE;

 39 void display(NODE *head)
 40 {    
 41     EMPLOYEE *emp;
 42     NODE *temp;
 43      
 44     printf ("[HEAD]");
 45     for (temp=head->next; temp != head; temp=temp->next) 
 46     {
 47         emp = (EMPLOYEE*)((char*)temp - (unsigned long)(&((EMPLOYEE*)0)->list2)); 
 48         printf ("<->[%s]", emp);
 49     }
 50     printf("<->[HEAD]\n");
 51 }   
// container of - ์ผ๋ฐ˜ํ™”๋ฅผ ํ•˜๊ธฐ ์œ„ํ•ด macro๋ฅผ ์ง€์›ํ•˜์ž ! 
  1 #include <stdio.h>
  2 #define container_of(ptr, type, member) \
  3     (type*)((char*)ptr - (unsigned long)&((type*)0)->member)                                                                                                                                                  
  4      
  5 typedef struct
  6 {    
  7     int a;
  8     int b;
  9     int c;
 10 } AA;
 11      
 12 int main()
 13 {    
 14     AA aa = {1, 2, 3};
 15     int *temp = &aa.c;
 16      
 17     AA *p = container_of(temp, AA, c);
 18     // AA *p = (AA*)((char*)temp - (unsigned long)(&((AA*)0)->c));
 19      
 20     printf ("[TEST] a, b, c : %d %d %d\n", p->a, p->b, p->c);
 21     return 0;
 22 }    

โ€ป gcc -E ๋ฅผ ํ†ตํ•ด ์ „์ฒ˜๋ฆฌ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Œ

12. open source example

macro๋Š” const ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์Œ. 
macro์— ์‚ฌ์šฉ๋˜๋Š” ์ธ์ž๋Š” type์„ ์ง€์ •ํ•  ์ˆ˜ ์—†๊ณ  symbol๋งŒ ์ง€์ •ํ•  ์ˆ˜ ์žˆ์Œ

โ†’ const๋ฅผ ํ‰๋‚ด๋‚ด๊ธฐ ์œ„ํ•ด์„œ ๋‚ด์žฅ macro๋ฅผ ์‚ฌ์šฉํ•˜์ž ! 
  1 #include <stdio.h>                                                                                                                                                                                            
  2  
  3 #define __FOO(x)                    \
  4     printf("data = %d\n", *(x))
  5  
  6 #define FOO(x)                      \
  7     const typeof(*(x)) *__x = x;    \ 
  8     __FOO(__x)
  9  
2์ค„ ์ด์ƒ์˜ macro์—์„œ๋Š” do while ๋ฌธ์„ ์‚ฌ์šฉํ•ด์•ผ ํ•˜์ง€๋งŒ, ์ด๋ฅผ macro์— ์‚ฌ์šฉํ•  ๊ฒฝ์šฐ do while ๋ฌธ์€ ์ œ์–ด๋ฌธ์ด๊ธฐ ๋•Œ๋ฌธ์— return ๊ฐ’์„ ๋ฐ›์•„์˜ฌ ์ˆ˜ ์—†๋‹ค. 

โ†’ return ๊ฐ’์„ ๊ฐ–๋Š” macro๋ฅผ ์“ฐ์ž ! do while ๋ฌธ ๋Œ€์‹  ์†Œ๊ด„ํ˜ธ๋ฅผ ์‚ฌ์šฉํ•˜์ž ({ ... }) ์ด์šฉํ•˜๊ธฐ 
๊ทธ๋Ÿฌ๋ฉด ์ตœ์ข… expression ๊ฐ’์ด return ๊ฐ’์ด ๋œ๋‹ค. ! 

์ตœ์ข… ์ฝ”๋“œ์—๋Š”, 
- macro ์—์„œ ์•ˆ๋˜๋Š” const ์— ๋Œ€ํ•œ ๊ณ ๋ ค๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ์Œ
- macro ์—์„œ ์•ˆ๋˜๋Š” return ๊ฐ’์ด ์•ˆ๋˜๋Š” ์†Œ๊ด„ํ˜ธ ๋ฌธ๋ฒ•์ด ๋“ค์–ด๊ฐ€ ์žˆ์Œ 
 13 #define container_of(ptr, type, member) ({                  \ 
 14     const typeof( ((type*)0)->member ) *__mptr = (ptr);     \
 15     (type*)( (char*)__mptr - offsetof(type, member) );})    \ 

ยง Hash

1. Intro

- linked list์˜ ๋ฌธ์ œ์ 
    1) ์ตœ์•…์˜ ๊ฒฝ์šฐ Big O(N), N๋ฒˆ ์ˆœํšŒํ•ด์•ผ ํ•œ๋‹ค. 
- hash
    1) bucket pointer๋กœ ๋‚˜๋ˆˆ๋‹ค. 
    2) ๊ฐ node๋ฅผ insertํ•  ๋•Œ hash ๊ฐ’์„ ๊ณ„์‚ฐํ•˜์—ฌ ํ•ด๋‹น๋˜๋Š” ๋ฐ์— ๋„ฃ๋Š”๋‹ค. 
    3) memory ๋ฅผ ๋” ์‚ฌ์šฉํ•จ์œผ๋กœ์จ ๋ถ„์‚ฐ ๋ฐฐ์น˜๋ฅผ ์ด์šฉํ•˜์—ฌ ํšจ์œจ์„ ๋†’์ธ๋‹ค. 
    4) hash function ์ด ์•Œ๊ณ ๋ฆฌ์ฆ˜์˜ ์„ฑ๋Šฅ์„ ์ขŒ์ง€์šฐ์ง€ํ•œ๋‹ค. 

2. Generic hash์˜ ํƒ€์ž… ์„ค๊ณ„ ๋ฐ ๊ตฌํ˜„

- hash heads 
  + 1์ค‘ ํฌ์ธํ„ฐ *first (๊ธฐ๋ณธ์ ์œผ๋กœ NULL) 

- hash
  + 1์ค‘ ํฌ์ธํ„ฐ *next 
  + 2์ค‘ ํฌ์ธํ„ฐ **pprev  โ†’ why? pointer์™€ node๋ฅผ ๊ฐ™์ด ๊ฐ€๋ฆฌํ‚ค๊ธฐ ์œ„ํ•ด์„œ  
  1 #include <stdio.h>     
  2 #include <stdlib.h>
  3 #define MAX 8
  4         
  5 #define container_of(ptr, type, member)     \
  6     (type*)((char*)ptr - (unsigned long)&((type*)0)->member)
  7         
  8 struct hlist_head {
  9     struct hlist_node *first;
 10 };      
 11         
 12 struct hlist_node {
 13     struct hlist_node *next, **pprev;
 14 };      
 15         
 16 typedef struct {
 17     int no;
 18     struct hlist_node hash;
 19 } data; 
 20         
 21         
 22 void hlist_add_head(struct hlist_node *n, struct hlist_head *h)
 23 {       
 24     struct hlist_node *first = h->first; 
 25         
 26     n->next = first;
 27     if (first)
 28         first->pprev = &n->next;
 29     h->first = n;
 30     n->pprev = &h->first;
 31         
 32 }       
 33         
 34 void display(struct hlist_head *h)
 35 {       
 36     int i;
 37     struct hlist_node *temp;
 38     data *d;
 39     system("clear");
 40         
 41     for (i=0; i<MAX; i++)
 42     {   
 43         printf ("[%d]", i);
 44         for(temp=h[i].first; temp; temp=temp->next)
 45         {
 46             d = container_of(temp, data, hash); 
 47             printf("<->[%d]", d->no);
 48         }
 49         printf ("\n");
 50     }
 51     getchar();
 52 }
 53  
 54 int hash_function(int n)
 55 {
 56     return n % MAX;
 57 }
 58  
 59 int main(void)
 60 {
 61     struct hlist_head heads[MAX] = {0,};
 62     data d[30] = {0,};
 63     int i, sno;
 64  
 65     for (i=0; i<30; i++) {
 66         sno = 1000 + i;
 67         d[i].no = sno;
 68         hlist_add_head( &d[i].hash, &heads[hash_function(sno)]);
 69         display(heads);
 70     }
 71  
 72  
 73     return 0;
 74 }                                  
// hash function
  2 #define GOLDEN_RATIO_PRIME_32 0x9e370001UL 
 ...
 32 unsigned int hash_32(unsigned int val, unsigned int bits)
 33 {    
 34     unsigned int hash = val * GOLDEN_RATIO_PRIME_32;
 35     return hash >> (32 - bits);
 36 }  

ยง Binary Search Tree

1. Intro

- Terms 
  + root : level = 0
  + level 
  + leaf : level = depth of tree
  + degree : ์ตœ๋Œ€ ๊ฐ€์ง€ ์ˆ˜ 
- ํ•˜๋‚˜์˜ node์—์„œ ๋‹ค๋ฅธ node๋กœ ๊ฐ€๋Š” ๋ฐฉ๋ฒ•์ด 1๊ฐœ๋งŒ ์กด์žฌํ•˜๋ฉด tree, 2๊ฐœ ์ด์ƒ ์กด์žฌํ•  ๊ฒฝ์šฐ์—๋Š” graph ๋ผ๊ณ  ํ•œ๋‹ค. ํ๊ณก์„  (circle) ์ด 1๊ฐœ๋ผ๋„ ์กด์žฌํ•˜๋ฉด graph ์ด๋‹ค.
  1 #include <stdio.h>
  2 #include <stdlib.h>
  3      
  4 typedef enum { LEFT, RIGHT } FLAG;
  5      
  6 typedef struct _node
  7 {    
  8     int data;
  9     struct _node *left;
 10     struct _node *right;
 11 } NODE;
 12      
 13 NODE *root;
 14      
 15 void insert_data(int data, NODE *ref, FLAG flag)
 16 {    
 17     NODE *temp;
 18     temp=malloc(sizeof(NODE));
 19     temp->data = data;
 20     temp->left = 0;
 21     temp->right = 0;
 22      
 23     if(root == 0)
 24     {
 25         root = temp;
 26         return;
 27     }
 28     if (flag == LEFT) ref->left = temp;
 29     else if (flag == RIGHT) ref->right = temp;                                                                                                                                                                
 30 }    
 31      
 32 int main(void)
 33 {    
 34     insert_data(1, root, LEFT);
 35     insert_data(2, root, LEFT);
 36     insert_data(3, root, RIGHT);
 37      
 38     insert_data(4, root->left, LEFT);
 39     insert_data(5, root->left, RIGHT);
 40      
 41     insert_data(6, root->right, LEFT);
 42     insert_data(7, root->right, RIGHT);
 43      
 44     return 0;
 45 }    

2. Tree order traverse

tree๋Š” ๋น„์„ ํ˜• ์ž๋ฃŒ ๊ตฌ์กฐ์ด๋ฏ€๋กœ ์ „์ฒด ์ˆœํšŒํ•˜๊ธฐ๊ฐ€ ์–ด๋ ต๋‹ค. 
- pre order: root - left - right 
  + 1 2 4 5 3 6 7 

- in order: left - root - right 
  + 4 2 5 1 6 3 7 

- post order: left - right - root
  + 4 5 2 6 7 3 1
  32 // pre order 
 33 void pre_order(NODE *temp)
 34 {    
 35     if (temp == 0) return;
 36      
 37     printf ("%d\n", temp->data);
 38     pre_order(temp->left);
 39     pre_order(temp->right);
 40 }    
 41      
 42 // in order
 43 void in_order(NODE *temp)
 44 {    
 45     if (temp == 0) return;
 46      
 47     in_order(temp->left);
 48     printf("%d\n", temp->data);
 49     in_order(temp->right);
 50 }    
 51      
 52 // post order 
 53 void post_order(NODE *temp)
 54 {    
 55     if (temp == 0) return;
 56      
 57     post_order(temp->left);
 58     post_order(temp->right);
 59     printf("%d\n", temp->data);
 60 }   

3. Tree display function

- in_order ์ˆœํšŒ๋ฅผ ํ•˜์ง€๋งŒ, display ๊ฐ€ ๊ฑฐ์šธ์— ๋’ค์ง‘ํžŒ ๊ฒƒ์ฒ˜๋Ÿผ ๋˜๊ธฐ ๋•Œ๋ฌธ์— ๋ฐ˜๋Œ€๋กœ ์ˆœํšŒ๋ฅผ ํ•œ๋‹ค ! 
โ€ป static : ํ•จ์ˆ˜ scope ์ œํ•œ์ ์ด์ง€๋งŒ, ์ „์—ญ ๋ณ€์ˆ˜์ด๊ธฐ ๋•Œ๋ฌธ์— ํ•จ์ˆ˜์—์„œ ๊ฐ’์„ ๊ณ„์† ์œ ์ง€ํ•˜๊ฒŒ ๋จ.
ํ•˜์ง€๋งŒ ์ด ํ•จ์ˆ˜๋ฅผ ์—ฌ๋Ÿฌ๋ฒˆ ํ˜ธ์ถœํ•˜๊ฒŒ ๋˜๋ฉด static ๊ฐ’์ด ๊ณ„์† ์œ ์ง€๋œ๋‹ค. 

- ์œ„ ๋ฐฉ๋ฒ•์€, tree๊ฐ€ ์„ธ๋กœ๋กœ ์ถœ๋ ฅ๋˜๋ฏ€๋กœ ๊ฐ€๋กœ๋กœ ์ถœ๋ ฅํ•˜๋ ค๋ฉด array ์— ๋„ฃ์–ด์ฃผ๋ฉด ๋œ๋‹ค.
์ด ๋•Œ, display ํ•จ์ˆ˜์™€ __display ํ•จ์ˆ˜๋ฅผ ์“ฐ๊ฒŒ ๋˜๋Š”๋ฐ, 
__display ๋Š” ๋ฐฐ์—ด์— ๊ฐ’์„ ๋„ฃ์–ด์ฃผ๋Š” ์—ญํ• ์„ ํ•˜๋ฉฐ, return ๊ฐ’์œผ๋กœ 2์ฐจ์› ๋ฐฐ์—ด์„ ๋„˜๊ฒจ์ค€๋‹ค. 
์ด ๋•Œ int(* __function(type *var))[size] ์ด๋Ÿฐ ์‹์œผ๋กœ ํ•˜๋ฉด 2์ฐจ์› ๋ฐฐ์—ด์„ return ๊ฐ’์œผ๋กœ ์„ค์ • ๊ฐ€๋Šฅ
(๊ณ ๊ธ‰ C๋ฌธ๋ฒ• ์ฐธ์กฐ)

- ํ•˜์ง€๋งŒ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ๋ฐฐ์—ด๋„ ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ• ๋•Œ๋งˆ๋‹ค ์ดˆ๊ธฐํ™” ๋˜์–ด์•ผ ํ•˜๋ฏ€๋กœ static์ด ์•„๋‹Œ ๋‹ค๋ฅธ ๊ฑธ ์‚ฌ์šฉํ•ด๋ณด์ž ! 
call by address ๋กœ ๋„˜๊ฒจ์ฃผ์ž

 63 // display  
 64 int (*__display(NODE *temp))[MAX]
 65 {    
 66     int i;
 67     static int row = -1;
 68     static int col = 0;
 69     static int tree[MAX][MAX] = {0,};
 70      
 71     if (temp == 0) return tree;
 72      
 73     ++row;
 74     __display(temp->left);
 75     tree[row][col++] = temp->data;
 76     __display(temp->right);
 77     --row; 
 78     return tree;
 79 }    
 80      
 81 void display(NODE *temp)
 82 {    
 83     int (*tree)[MAX];
 84     int i, j; 
 85     tree = __display(temp);
 86      
 87     system("clear");
 88     for(i=0; i<MAX; i++)
 89     {     
 90         for (j=0; j<MAX; j++)
 91         { 
 92             if (tree[i][j]) 
 93                 printf("%3d", tree[i][j]);
 94             else
 95                 printf("%3c", ' ');
 96         } 
 97         printf("\n");
 98     }     
 99     getchar();
100 }    
 63 // display final   
 64 void __display(NODE *temp, int (*tree)[MAX], int *row, int *col)
 65 {                 
 66     if (temp == 0) return;
 67                   
 68     ++*row;       
 69     __display(temp->left, tree, row, col);
 70     tree[*row][++*col] = temp->data;
 71     __display(temp->right, tree, row, col);
 72     --*row;       
 73 }                 
 74                   
 75 void display(NODE *temp)
 76 {                 
 77     int row = -1; 
 78     int col = 0;  
 79     int tree[MAX][MAX] = {0,};
 80     __display(temp, tree, &row, &col);
 81                   
 82     system("clear");
 83     int i, j;     
 84                   
 85     for(i=0; i<MAX; i++)
 86     {             
 87         for (j=0; j<MAX; j++)
 88         {         
 89             if (tree[i][j]) 
 90                 printf("%3d", tree[i][j]);
 91             else  
 92                 printf("%3c", ' ');
 93         }         
 94         printf("\n");
 95     }             
 96     getchar();    
 97 }                 

4. Binary search tree insert

 16 void insert_data(int data)                                                                                                                                                                                    
 17 {    
 18     NODE *temp, *p=root, *prev;
 19     temp = (NODE*)malloc(sizeof(NODE));
 20      
 21     temp->data = data;
 22     temp->right = 0;
 23     temp->left = 0;
 24      
 25     if (root == 0)
 26     {
 27         root = temp;
 28         return;
 29     }
 30      
 31     while(p)
 32     {
 33         prev = p;
 34         if (p->data > data)
 35             p = p->left;
 36         else if (p->data < data)
 37             p = p->right;
 38         else
 39             return;
 40     }
 41      
 42     if (prev->data > data)
 43         prev->left = temp;
 44     else 
 45         prev->right = temp;
 46 }  
- ์ƒˆ๋กœ ๋“ค์–ด์˜ค๋Š” ๊ฐ’์ด root node ๊ฐ’๋ณด๋‹ค ์ž‘์œผ๋ฉด ์™ผ์ชฝ, ํฌ๋ฉด ์˜ค๋ฅธ์ชฝ์—
   + ์ด ๊ฒฝ์šฐ O(log2N)  
   + ๋˜ํ•œ ์ค‘๋ณต์„ ํ—ˆ์šฉํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ ๊ฐ™์€ ๊ฐ’์ด ๋“ค์–ด์˜ค๋ฉด ๋ฐ”๋กœ return;
 
- insert function
   + curr (pointer)์„ root (pointer)๋ถ€ํ„ฐ (*curr = root) ์ถœ๋ฐœ 
   + ํ•˜์ง€๋งŒ curr์„ 1์ค‘ ํฌ์ธํ„ฐ๋กœ ํ•˜๊ฒŒ ๋˜๋ฉด code redundancy 
   + ๊ฒฐ๋ก  : curr์„ 2์ค‘ ํฌ์ธํ„ฐ๋กœ ํ•œ๋‹ค ! __**(**curr = &root)**__
   + ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด root == 0 ์ผ ๋•Œ์˜ ๋น„๊ต ํ•  ํ•„์š” ์—†์Œ
   + ๋˜ํ•œ, while(curr) ๋Œ€์‹  while(*curr) ์„ ์‚ฌ์šฉํ•˜๊ฒŒ ๋˜๋ฉด NULL ์ผ๋•Œ ์ž๋™์œผ๋กœ ๋น ์ ธ๋‚˜์˜ด
   + while ๋ฌธ์„ ์ˆ˜ํ–‰ํ•˜๋Š” ์ค‘์— ์ ์ ˆํ•œ ์ž๋ฆฌ๋ฅผ ๋งŒ๋‚˜๋ฉด, curr๋Š” NULL ์„ ๊ฐ€๋ฆฌํ‚ค๋Š”๊ฒŒ ์•„๋‹ˆ๋ผ curr ๊ฐ€ ๊ฐ€๋ฆฌํ‚ค๋Š” ํฌ์ธํ„ฐ์˜ left๋ฅผ ๊ฐ€๋ฆฌํ‚ค๊ฒŒ ๋จ.
   + left๋Š” NULL ์ด์ง€๋งŒ left์˜ ๋ฒˆ์ง€๋ฅผ ๊ฐ€๋ฆฌํ‚ค๊ธฐ ๋•Œ๋ฌธ์— curr๋Š” NULL์€ ์•„๋‹˜
   + while ๋ฌธ์„ ๋น ์ ธ๋‚˜์˜ค๋ฉด *curr = temp; ๋ผ๊ณ ๋งŒ ๋„ฃ์œผ๋ฉด ๋จ. 
   + ์ฆ‰, curr์€ root ๋ผ๋Š” pointer๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š” pointer ๊ฐ€ ๋œ๋‹ค.  
 48 void insert_data_final(int data)
 49 {    
 50     NODE *temp;
 51     NODE **curr = &root;
 52      
 53     temp = (NODE*)malloc(sizeof(NODE));
 54     temp->data = data;
 55     temp->right = 0;
 56     temp->left = 0;
 57      
 58     while(*curr)
 59     {
 60         if ( (*curr)->data > data ) 
 61             curr = &(*curr)->left;
 62         else if ( (*curr)->data < data )
 63             curr = &(*curr)->right;
 64         else
 65             return;
 66     }
 67     *curr = temp;
 68 }    

5. Binary search tree balance

- balance๊ฐ€ ๋งž์ง€ ์•Š๋Š” tree๋Š” ์ตœ์•…์˜ ๊ฒฝ์šฐ O(N) ์ด๋ฉฐ ์ด๋Š” linked list์™€ ๋™์ผํ•˜๋‹ค.
- ๋”ฐ๋ผ์„œ ๊ฐ’์ด ์–ด๋–ป๊ฒŒ ๋“ค์–ด์˜ค๋”๋ผ๋„, balance๋ฅผ ๋งž์ถฐ์ฃผ๋Š” ๊ฒŒ ํ•„์š”ํ•˜๋‹ค.
   + 1์ฐจ์› sorted ๋ฐฐ์—ด๋กœ ๋งŒ๋“ค์–ด ์ฃผ๋Š” __fill ์ด๋ผ๋Š” ํ•จ์ˆ˜๋ฅผ ๊ตฌํ˜„ํ•œ๋‹ค 
   + user interface ๊ฒธ bal ํ•จ์ˆ˜ : ์ธ์ž๋ฅผ ์ฑ„์šฐ๋Š” ์—ญํ• 
   + __bal ํ•จ์ˆ˜๋Š” bal ์—์„œ mid๋ฅผ ์ฐพ์•„์„œ ์—ฐ๊ฒฐ์‹œ์ผœ์ฃผ๋Š” ์—ญํ• ์„ ํ•˜๋Š” ํ•จ์ˆ˜ 
   + __bal ํ•จ์ˆ˜๋Š” return ๊ฐ’์ด NODE* ๊ฐ€ ๋˜์–ด์•ผ ํ•œ๋‹ค. 
   + ์ด ๋•Œ __bal ํ•จ์ˆ˜๋ฅผ ์žฌ๊ท€์ ์œผ๋กœ ํ˜ธ์ถœํ•˜๋Š”๋ฐ array ์˜ size์ธ n > 0 ์ผ๋•Œ๋Š” temp๋ฅผ return ํ•˜๊ณ  ๊ทธ ์™ธ์—๋Š” 0์„ return 

- ๊ธฐ์กด์— ๋“ค์–ด์˜จ tree๋ฅผ ํŒŒ๊ดดํ•˜์—ฌ 1์ฐจ ๋ฐฐ์—ด๋กœ ์ •๋ ฌ ํ›„ ๋‹ค์‹œ balance tree ๋งŒ๋“ค์–ด๋„ ๋˜๋Š”๋ฐ, ์ด๋ ‡๊ฒŒ ๋˜๋ฉด ์‹ค์‹œ๊ฐ„ balance๊ฐ€ ์•„๋‹ˆ๋‹ค. ์ฃผ๊ธฐ์ ์œผ๋กœ balance ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ• ํ…๋ฐ, ํ˜ธ์ถœ ์ „๊นŒ์ง€๋Š” balance๊ฐ€ ๋งž์ง€ ์•Š๋Š”๋‹ค. 
- ๋˜ node๊ฐ€ 10๋งŒ๊ฐœ ๋˜๋Š” code์—์„œ๋Š” tree๋ฅผ ๋‹ค์‹œ ํŒŒ๊ดดํ•˜๊ณ  ๋‹ค์‹œ ๋งŒ๋“ค๊ธฐ์—๋Š” overhead๊ฐ€ ์žˆ๋‹ค. 
- ์ƒˆ๋กœ์šด tree๋“ค์ด ์—ฐ๊ตฌ๋˜๊ธฐ ์‹œ์ž‘ ! ๋ฐ”๋กœ RB tree 

ยง Red Black Tree

1. Intro

  • AVL tree : ๊ฐ€์ค‘์น˜๋ฅผ ๋‘ฌ์„œ balance๋ฅผ ๋งž์ถ”๋Š” tree
  • 2-3 tree /2-3-4 tree
  • B tree / B+ tree / B* tree
  • Read Black Tree!!

2. RB Tree insert rule โ€ป node ์˜ parent๋ฅผ parent ๋ผ๊ณ  ํ•˜๊ณ  ๊ทธ์˜ parent๋ฅผ gparent, ๊ทธ๋ฆฌ๊ณ  gparent์˜ ๋˜๋‹ค๋ฅธ ์ž์‹์„ uncle ์ด๋ผ๊ณ  ํ•œ๋‹ค.

  • ground rule !
    root ๋…ธ๋“œ๋กœ๋ถ€ํ„ฐ ๋ชจ๋“  ๋‹จ๋ง ๋…ธ๋“œ๋กœ ๊ฐ€๋Š” ๊ฒฝ๋กœ์˜ ๊ฒ€์ •๋…ธ๋“œ์˜ ์ˆ˜๊ฐ€ ๊ฐ™์œผ๋ฉด !! balance๊ฐ€ ๋งž๋Š” ๊ฒƒ์œผ๋กœ ๊ฐ„์ฃผํ•œ๋‹ค.

  • ์ฒซ์งธ, ์ƒˆ๋กœ์šด ๋…ธ๋“œ๋Š” RED ์ด๋‹ค. โ†’ root ๋…ธ๋“œ ๋“ฑ์žฅ์œผ๋กœ ๋‘˜์งธ ๋ฃฐ๋กœ ๋ฐ€๋ ค๋‚จ.

  • ์ฒซ์งธ, root ๋…ธ๋“œ๋Š” ์–ธ์ œ๋‚˜ BLACK ์ด๋‹ค.

  • ์…‹์งธ, ๋ถ€๋ชจ๊ฐ€ RED ์ด๋ฉด ํšŒ์ „ํ•œ๋‹ค. โ†’ ๋„ค๋ฒˆ์งธ

    • color flip parent color => BLACK gparent color => RED
    • ๊ฒฝ์‚ฌ๋ฅผ ๋ณธ๋‹ค. R-R ๊ฒฝ์‚ฌ => rotate_left(gparent) (rotate ์‹œ ์ด๋ฏธ ์ž์‹ node๊ฐ€ ์žˆ์œผ๋ฉด ์ž…์–‘์„ ํ•˜๊ณ  ๋‚ด๋ ค์˜จ๋‹ค.)
    • ์…‹์งธ ๋ฃฐ์€, uncle์ด ์žˆ์„ ๊ฒฝ์šฐ ํ•ด๊ฒฐ๋˜์ง€ ์•Š์œผ๋ฏ€๋กœ ๋„ค๋ฒˆ์งธ ๋ฃฐ๋กœ ๋ฐ€๋ ค๋‚œ๋‹ค.
  • ์…‹์งธ, parent๋„ RED, uncle๋„ RED์ด๋ฉด color flip ๋งŒ ํ•œ๋‹ค.

    • color filp parent, uncle => BLACK gparent => RED

์ •๋ฆฌํ•˜๋ฉด,

  • ์œ ์‚ฌ ๋ฐธ๋Ÿฐ์Šค ์กฐ๊ฑด: ๋‹จ๋ง ๋…ธ๋“œ๊นŒ์ง€ ๊ฒฝ๋กœ ์ค‘ BLACK ๋…ธ๋“œ ์ˆ˜๊ฐ€ ๊ฐ™์œผ๋ฉด balance๊ฐ€ ๋งž๋Š” ๊ฒƒ์œผ๋กœ ๊ฐ„์ฃผํ•œ๋‹ค.
  • root ๋…ธ๋“œ๋Š” ์–ธ์ œ๋‚˜ BLACK ์ด๋‹ค.
  • ์ƒˆ๋กœ์šด ๋…ธ๋“œ๋Š” RED ์ด๋‹ค.
  • ๋ถ€๋ชจ๊ฐ€ RED, ์‚ผ์ดŒ๋„ RED ์ด๋ฉด color flip ๋งŒ ํ•œ๋‹ค.
  • ๋ถ€๋ชจ๊ฐ€ RED ์ด๋ฉด color flip ๊ณผ rotate ํ•œ๋‹ค.

4. RB Tree insert code

ยง Augment Tree

1. Intro

  • ์งˆ๋ฌธ : ์•ŒํŒŒ๋ฒณ ์ˆœ์„œ์ƒ 5๋ฒˆ์งธ ์‚ฌ๋žŒ์€ ?
  • ๋ฌธ์ œ์  : ์ด N๊ฐœ ์ค‘ N์— ๊ฐ€๊นŒ์šด ์‚ฌ๋žŒ์„ ์ฐพ์„๋•Œ์—๋Š” ์‹œ๊ฐ„์ด ๋” ์˜ค๋ž˜ ๊ฑธ๋ฆฐ๋‹ค (์ตœ์•…์˜ ๊ฒฝ์šฐ O(N))
  • ํ•ด๊ฒฐ์ฑ… : ์ฆ๊ฐ•๊ฐ’์„ ์ถ”๊ฐ€ํ•œ๋‹ค ! (augment) : size ๋ผ๊ณ  ๋ถ€๋ฅธ๋‹ค.
    • leaf node ์—๋Š” augment = 1 ๋กœ setting
    • parent node ์—๋Š” child node ๋“ค์˜ augment์˜ ํ•ฉ + 1 ์„ ๋„ฃ๋Š”๋‹ค.
  • ์ฐพ๊ณ ์ž ํ•˜๋Š” index i, i์™€ ๋น„๊ตํ•˜๋Š” ๊ธฐ์ค€์  k (์ดˆ๊ธฐ๊ฐ’์€ ์™ผ์ชฝ sub-tree์˜ augment + 1)
  • ๊ธฐ์ค€์  k ๋ณด๋‹ค i๊ฐ€ ์ž‘์„ ๋•Œ์—๋Š” ์™ผ์ชฝ์œผ๋กœ ์ด๋™
    • ์™ผ์ชฝ์œผ๋กœ ์ด๋™ํ•  ๋•Œ์—๋Š” i๋Š” ๊ทธ๋Œ€๋กœ ์žˆ๊ณ , k๋Š” ๋‹ค์‹œ ์™ผ์ชฝ sub tree์˜ augment + 1 ๋กœ ๋‹ค์‹œ setting
  • ๊ธฐ์ค€์  k ๋ณด๋‹ค i๊ฐ€ ํด ๋•Œ์—๋Š” ์˜ค๋ฅธ์ชฝ์œผ๋กœ ์ด๋™
    • ์˜ค๋ฅธ์ชฝ์œผ๋กœ ์ด๋™ํ•  ๋•Œ์—๋Š” i := i - k, k ๋Š” ์™ผ์ชฝ sub tree์˜ augment + 1 ๋กœ setting (null ์ด๋ฉด 0์œผ๋กœ ๋ด„)
  • ๊ธฐ์ค€์  k ์™€ i๊ฐ€ ๊ฐ™์„ ๋•Œ ๋ฐ”๋กœ ์ฐพ๊ณ ์ž ํ•˜๋Š” ๊ณณ !!
  • ์ด๋ ‡๊ฒŒ ๋งŒ๋“ค์–ด์ง„ tree๋ฅผ ๋™์  ํ†ต๊ณ„ tree ๋ผ๊ณ  ํ•œ๋‹ค.
  • ์ด๋Ÿฐ ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ select ์•Œ๊ณ ๋ฆฌ์ฆ˜ ์ด๋ผ๊ณ  ํ•œ๋‹ค.

ยง Flexible Array

1. Intro

  • flexible array ๋ฅผ pointer๋กœ ์žก์•„์„œ, ๋™์ ์œผ๋กœ memory ํ• ๋‹น

https://github.com/imguru-mooc/opensource-datastructure-algorithm

โš ๏ธ **GitHub.com Fallback** โš ๏ธ