일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- WinAPI
- html
- 수광 소자
- 라인트레이서
- LineTracer
- arduino compiler
- priority_queue
- C언어
- Visual Micro
- Arduino
- stl
- c++
- 운영체제
- 자료구조
- 시스템프로그래밍
- map
- Algorithm
- vector
- 통계학
- Array
- list
- Stack
- 아두이노 컴파일러
- 컴퓨터 그래픽스
- queue
- Deque
- set
- directx
- 아두이노 소스
- 아두이노
- Today
- Total
Kim's Programming
[C로 만드는 자료구조]이진 탐색 트리(Binary Search Tree) 본문
[C로 만드는 자료구조]이진 탐색 트리(Binary Search Tree)
Programmer. 2015. 12. 25. 16:56이진 탐색 트리(Binary Search Tree) - 정의
- 모든 원소는 서로 다른 유일한 키를 가짐
- 왼쪽 서브트리에 있는 원소들의 값은 그 루트의 값보다 작음
- 오른쪽 서브트리에 있는 원소의 값들은 그 루트의 값보다 큼
- 왼쪽 서브트리와 오른쪽 서브트리도 이진 탐색 트리임
- x = 루트 노드의 키 값 인 경우 : 원하는 원소를 찾았으므로 탐색 연산 성공
- x < 루트노드의 키 값 인 경우 : 루트 노드의 왼쪽 서브 트리에 대해서 탐색
- x > 루트노드의 키 값 인 경우 : 루트 노드의 오른쪽 서브 트리에 대해서 탐색
- 11을 루트 노드의 키 값 8과 비교 -> 오른쪽으로 이동
- 11과 10을 비교 -> 오른쪽으로 이동
- 11과 14를 비교 -> 왼쪽으로 이동
- 맞는값 찾으면 종료
삽인 연산 과정을 다음과 같은 그림으로 나타낼 수 있습니다.
이진 탐색트리에서 삭제연산은 좀 고려해줘야 할 것이 많습니다. 하지만 우선 삭제 연산의 순서 부터 알아보겠습니다. 우선 삭제할 값에 대한 값을 트리에서 탐색을 해야 합니다. 그 다음 은 찾은 노드를 삭제해야 하는데 3가지 경우로 나누어서 삭제경우를 나누어야 합니다.
- 삭제할 노드가 단말 노드인 경우 : 차수가 0인 경우
- 삭제할 노드가 하나의 자식 노드를 가진 경우 : 차수가 1인 경우 : 차수가 1인 경우
- 삭제할 노드가 두 개의 자식 노드를 가진 경우 : 차수가 2인 경우
단말 노드 삭제 연산은 다음과 같은 연산 과정을 거치게 됩니다. 탐색을 통해서 위치를 찾아간 다음 맞는 위치를 찾으면 대상 노드를 삭제만 하면 끝납니다.
차수가 1일 경우
탐색을 통하여 찾아갔는데 차수가 1인 경우에는 대상 노드의 자식노드를 지우려는 대상 노드의 자리에 끼워넣어주고 대상 노드는 삭제해 줍니다.
차수가 2일 경우
2차의 경우는 좀 어렵습니다. 1차의 경우처럼 노드를 삭제하면 붙일게 하나가 아니라 2개가 되는데 이럴 때는 삭제하는 노드와 가장 비슷한 값을 가지는 노드를 삭제 노드 위치로 가져와서 삭제를 시켜줍니다. 다음은 후계자 선택 방법(삭제된 자리에 채워넣는 대상) 2가지입니다.
후계자 선택방법은 다음과 같습니다.
- 왼쪽 서브트리에서 가장 큰 자손을 선택. 즉, 루트의 왼쪽 자식노드를 루트로 하는 트리에서 가장 오른쪽에 있는 노드가 됩니다.
- 오른쪽 서브트리에서 가장 작은 자손을 선택. 즉, 루트의 오른쪽 자식노드를 루트로 하는 트리에서 가장 오른쪽에 있는 노드가 됩니다.
이진 탐색 트리(Binary Search Tree) - ADT 구현
구현은 3가지를 했습니다. 값이 있는 지 없는지 탐색하는 함수, 삽입하는 함수, 삭제하는 함수를 구현했습니다. 이진 탐색 트리를 구현할때는 트리구현때 처럼 다음과 같은 구조체들을 사용해서 구현합니다.
1 2 3 4 5 6 7 8 9 10 11 12 | #include<stdio.h> #include<malloc.h> struct TreeNode { int key; TreeNode *LNode; TreeNode *RNode; }; struct Tree { TreeNode *Root; }; | cs |
void Tree_Init()
1234void Tree_Init(Tree *Target_Tree){Target_Tree->Root = NULL;}cs 초기화 하는 함수입니다.
bool Is_There()
123456789101112131415161718192021222324bool Is_There(Tree *Target_Tree, int Item){TreeNode *Cur = Target_Tree->Root;while (1){if (Cur->key == Item){return true;}if (Cur->key < Item){if (Cur->RNode == NULL)return false;Cur = Cur->RNode;}else{if (Cur->LNode == NULL)return false;Cur = Cur->LNode;}}}cs 값이 있는지 없는지를 확인하는 함수입니다. 있을떄 true를 반환하고 없으면 false를 반환하게 됩니다.
void Add_Node()
123456789101112131415161718192021222324252627282930313233343536373839404142void Add_Node(Tree *Target_Tree, int Item){TreeNode *NewNode = (TreeNode *)malloc(sizeof(TreeNode));if (Target_Tree->Root == NULL){Target_Tree->Root = NewNode;NewNode->LNode = NULL;NewNode->RNode = NULL;NewNode->key = Item;return;}if (Is_There(Target_Tree, Item)){printf("이미 존재 하는 값입니다.\n");return;}NewNode->LNode = NULL;NewNode->RNode = NULL;NewNode->key = Item;TreeNode *Cur = Target_Tree->Root;while (1){if (Cur->key < Item){if (Cur->RNode == NULL){Cur->RNode = NewNode;return;}Cur = Cur->RNode;}else{if (Cur->LNode == NULL){Cur->LNode = NewNode;return;}Cur = Cur->LNode;}}}cs 값을 추가하는 함수입니다. 기준 보다 크면 오른쪽으로 기준보다 작으면 왼쪽으로 가며 탐색해서 실패하면 그 자리에 추가를 하게됩니다.
Delete_Node()
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687int Delete_Node(Tree *Target_Tree, int Item){TreeNode *Cur2=NULL;TreeNode *Cur = Target_Tree->Root;TreeNode *Par_Parent=NULL;TreeNode *Parent=NULL;TreeNode *Child=NULL;TreeNode *Left_Temp = NULL;int Key_return = 0;if (!Is_There(Target_Tree, Item)){printf("없는 값입니다.\n");return 0;}while (Cur->key != Item){if (Item > Cur->key){Par_Parent = Parent;Parent = Cur;Cur = Cur->RNode;}else{Par_Parent = Parent;Parent = Cur;Cur = Cur->LNode;}}//특정 값 까지 이동if (Cur->LNode == NULL&&Cur->RNode == NULL)//터미널 노드일 때{Key_return = Cur->key;if (Parent->LNode == Cur)Parent->LNode = NULL;if (Parent->RNode == Cur)Parent->RNode = NULL;free(Cur);return Key_return;}if (Cur->LNode == NULL || Cur->RNode == NULL)//지우려는 값 아래에 1개의 자식이 있을 때{Child = (Cur->LNode != NULL) ? Cur->LNode : Cur->RNode;if (Parent->LNode == Cur)//지우려는 값의 부모 의 어느자식이 지우려는 값인지?Parent->LNode = Child;elseParent->RNode = Child;Key_return = Cur->key;free(Cur);return Key_return;}if (Cur->LNode != NULL&&Cur->RNode != NULL)//지우려는 값 아래에 2개 자식이 있을 때{Cur2 = Cur;Cur2 = Cur2->RNode;if (Cur2->LNode == NULL)//오른쪽 한칸 이동 후 왼쪽에 노드가 없을 때{Left_Temp = Cur->LNode;Child = Cur2;if (Parent->RNode == Cur){Parent->RNode = Child;Child->LNode = Left_Temp;}elseif (Parent->LNode == Cur){Parent->LNode = Child;Child->LNode = Left_Temp;}Key_return = Cur->key;free(Cur);return Key_return;}while (Cur2->LNode != NULL)//오른쪽 한칸 이동후 왼쪽에 노드가 있을 때{Parent = Cur2;Cur2 = Cur2->LNode;}Parent->LNode = NULL;Cur->key = Cur2->key;free(Cur2);}return 0;}cs 삭제하는 연산입니다. 자식의 개수에 따라서 3가지로 나누기 때문에 소스가 좀 길어졌습니다.
'Programming > Data Structure' 카테고리의 다른 글
[C++/템플릿으로 만드는 자료구조] 단순원형연결리스트(Circular Linked List) (0) | 2016.01.18 |
---|---|
[C++/템플릿으로 만드는 자료구조] 단순연결리스트(Linked List) (1) | 2016.01.18 |
[C로 만드는 자료구조]우선순위 큐(Priority Queue) (2) | 2015.12.18 |
[C로 만드는 자료구조]이진 트리(Binary Tree) - 순회 (0) | 2015.12.18 |
[C로 만드는 자료구조]이진 트리(Binary Tree) - 배열 (6) | 2015.12.17 |