420 likes | 640 Views
Chapter 7. Binary Search Trees. [INA240] Data Structures and Practice Youn-Hee Han http://link.kut.ac.kr. 1. Basic Concepts. 무엇을 배우려고 하는가 ? (Motivation) Sometimes, we want to search an arbitrary element efficiently. Isn’t there any tree-based representation method for that situation?.
E N D
Chapter 7. Binary Search Trees [INA240] Data Structures and Practice Youn-Hee Han http://link.kut.ac.kr
1. Basic Concepts • 무엇을배우려고 하는가? (Motivation) • Sometimes, we want to search an arbitrary element efficiently. • Isn’t there any tree-based representation method for that situation? Binary tree Binary search tree
1. Basic Concepts • 무엇을배우려고 하는가? (Motivation) • Let’s first think just “Binary Search” • Random array: sequential search • Ex) finding 65 • Sorted array: binary search 35 38 70 75 12 25 18 54 65 90 86 pivot 12 18 25 35 38 54 6570 75 86 90 1st step 2nd step 3rd step 4rd step found!!
1. Basic Concepts • Binary search is more efficient than sequential search • Binary search is available for sorted array • Isn’t there a tree-based representation that has similar property with sorted array forbinary search? BST(Binary Search Tree)
1. Basic Concepts • Binary search tree (BST):binary tree that is • All items in left subtree are less than the root • All items in right subtree are greater than the root • Each subtree itself is a binary search tree BST의 예
1. Basic Concepts Ex) Which is/are binary search tree(s)? • There is an efficient algorithm to find an arbitrary element • Ex) Find 20 from the following BST 30 60 20 40 70 5 25 15 22 10 2 55 80 12
A[0] A[1] A[2] x A[n-1] 1st step 2nd step 3rd step root found!! < root > root 1. Basic Concepts • Binary search vs. BST BST는 “약하게 정렬되어 있다”라고 말할 수 있음 피벗(Pivot)을 중심으로 작은 것은 모두 왼쪽, 큰 것은 모두 오른쪽 서브트리만 놓고 볼 때도 다시 파티션 된 상태이다
2. BST Operations • Traversal • Preorder • 23 18 12 20 44 35 52 • Postorder • 12 20 18 35 52 44 23 • Inoder • 12 18 20 23 35 44 52 • Which order produces a sequenced list? Inorder Data Structure
2. BST Operations • Searchs • Find the smallest node • Find the largest node Algorithm findSmallestBST (root) 1. if (left subtree empty) 1. return (root) 2. end if 3. Return findSmallestBST (left subtree) end findSmallestBST Algorithm findLargestBST (root) 1. if (right subtree empty) 1. return (root) 2. end if 3. Return findLargestBST (right subtree) end findLargestBST Data Structure
2. BST Operations • Searchs • Find an arbitrary element • The most important feature of BST Algorithm searchBST (root, targetKey) 1. if (empty tree) 1. return null 2. end if 3. if (targetKey < root) 1. return searchBST (left subtree, targetKey) 4. else if (targetKey > root) 1. return searchBST (right subtree, targetKey) 5. else 1. return root 6. end if end searchBST Data Structure
2. BST Operations • Searchs • Find an arbitrary element • What if SearchBST tries to find a value that does not exist in the BST? • Ex) Finding 25 from the following BST Data Structure
2. BST Operations • Insertion • Inserting a node into a BST preserving requirements of BST • 삽입 할 새로운 노드는 Leaf Node로서 들어감 Data Structure
2. BST Operations • Insertion • Inserting Algorithm Algorithm addBST (root, newNode) 1. if (empty tree) 1. set root to newNode 2. return newNode 2. if (newNode < root) 1. return addBST (left subtree, newNode) 3. else 1. return addBST (right subtree, newNode) 4. end if end addBST 30 30 30 30 Data Structure
2. BST Operations • Deletion • Case 1: the node has no children just delete it 부모노드의 자신을 가리키는 포인터를 Null로 셋팅 - 노드 A 삭제 부모노드 B의 LChild를 Null로 셋팅 - 노드 K 삭제 부모노드 H의 RChild를 Null로 셋팅 Data Structure
2. BST Operations • Deletion • Case 2: the node has only left subtree delete the node make the left child the new root(삭제되는 노드의 왼쪽 자식을 삭제되는 노드자리로 이동) - 노드 F 삭제 F의 부모노드 G가 F의 자식노드인 B를 가리키면 됨 Data Structure
2. BST Operations • Deletion • Case 3: the node has only right subtree delete the node make the right child the new root(삭제되는 노드의 오른쪽 자식을 삭제되는 노드자리로 이동) - 노드 L 삭제 L의 부모노드 G가 L의 자식노드인 H를 가리키면 됨 Data Structure
2. BST Operations • Deletion • Case 4: the node has both left and right children • 노드 B를 삭제 노드 B의 부모인 F의 LChild가 동시에 A와 D를 가리키게? 안되지… • 노드 A를 B 자리로 이동 ? • 노드 D를 B 자리로 이동 ? • 둘다 가능하다. datacopy delete! “이동”에대한 처리: 1) 데이터만 실제삭제하려는 노드로 Copy 2) 이동 대상 자체를 삭제 Deletion을 다시 수행하므로 Recursion! Data Structure
2. BST Operations • Deletion • Case 4: the node has both left and right children • 노드 G를 삭제 우왕 복잡하다~~~~ • 이진 탐색트리를 중위순회(In-order Traversal)한 결과를 생각 : A < B < D < F < G < H < K < L • G가 삭제된 후에도 정렬된 순서를 그대로 유지하려면 G의 자리에는 G의 바로 오른쪽 H나, 아니면 G의 바로 왼쪽 F가 들어가야 함. • G 바로 다음에 나오는 H를 G의 중위 후속자(In-order Successor)라 하고, G 바로 직전에 나오는 F를 G의 중위 선행자(In-order Predecessor)라고 함. • 그래서, 결론적으로 G에 대한 중위 후속자나중위 선행자가 G의 자리로 옮겨져야 한다. datacopy Data Structure
2. BST Operations • Deletion • Case 4: the node has both left and right children delete the node replace it with the largest among left subtree or the smallest among the right subtree Algorithm deleteBST (root, dltKey) 1. if (empty tree) 1. return false 2. end if 3. if (dltKey < root) 1. return deleteBST (left subtree, dltKey) 4. else if (delKey > root) 1. return deleteBST (right subtree, dltKey) 5. else 1. if (no left subtree) 1. make right subtree the root 2. return true 2. if (no right subtree) 1. make left subtree the root 2. return true 20 25 15 27 12 Data Structure
2. BST Operations • Deletion • Case 4: the node has both left and right children delete the node replace it with the largest among left subtree or the smallest among the right subtree 3. else 1. save root in deleteNode 2. set largest to largestBST(left subtree) 3. move data in largest to deleteNode 4. return deleteBST(left subtree, largest) 4. end if 5. end if Data Structure
3. BST ADT • BST ADT Design Data Structure
3. BST ADT • Data representation Data Structure
3. BST ADT • Compare function (revisit) • Type-independent generic coding function pointer • Compare operation • int (*compare)(void *argu1, void *argu2); • 본교재에서는 다음과 같이 return 값이 정의됨 • Case I) argu1 의 데이터 > argu2 의 데이터 1 이 리턴됨 • Case II) argu1 의 데이터 < argu2 의 데이터 -1 이 리턴됨 • Case III) argu1 의 데이터 == argu2 의 데이터 0 이 리턴됨 Algorithm searchBST (root, targetKey) … 3. if (targetKey < root) 1. return searchBST (left subtree, targetKey) 4. else if (targetKey > root) 1. return searchBST (right subtree, targetKey) … Data Structure
3. BST ADT • BST Declarations • File Name: bst.h (이후 모든 ADT 구현은 이 한 파일에 추가) #include "stdbool.h" typedef struct node { void* dataPtr; struct node* left; struct node* right; } NODE; typedef struct { int count; int (*compare) (void* argu1, void* argu2); NODE* root; } BST_TREE; BST_TREE* BST_Create (int (*compare) (void* argu1, void* argu2)); BST_TREE* BST_Destroy (BST_TREE* tree); Data Structure
3. BST ADT • BST Declarations • File Name: bst.h bool BST_Insert (BST_TREE* tree, void* dataPtr); bool BST_Delete (BST_TREE* tree, void* dltKey); void* BST_Retrieve (BST_TREE* tree, void* keyPtr); void BST_Traverse (BST_TREE* tree, void (*process)(void* dataPtr)); bool BST_Empty (BST_TREE* tree); bool BST_Full (BST_TREE* tree); int BST_Count (BST_TREE* tree); static NODE* _insert (BST_TREE* tree, NODE* root, NODE* newPtr); static NODE* _delete (BST_TREE* tree, NODE* root, void* dataPtr, bool* success); static void* _retrieve (BST_TREE* tree, void* dataPtr, NODE* root); static void _traverse (NODE* root, void (*process) (void* dataPtr)); static void _destroy (NODE* root); Data Structure
3. BST ADT • Create BST BST_TREE* BST_Create (int (*compare) (void* argu1, void* argu2)) { BST_TREE* tree; tree = (BST_TREE*) malloc (sizeof (BST_TREE)); if (tree) { tree->root = NULL; tree->count = 0; tree->compare = compare; } return tree; } • stdbool.h #ifndef _STDBOOL_H #define _STDBOOL_H typedef int _Bool; #define bool _Bool #define true 1 #define false 0 #define __bool_true_false_are_defined 1 #endif Data Structure
3. BST ADT • Insert BST bool BST_Insert (BST_TREE* tree, void* dataPtr) { NODE* newPtr; newPtr = (NODE*)malloc(sizeof(NODE)); if (!newPtr) return false; newPtr->right = NULL; newPtr->left = NULL; newPtr->dataPtr = dataPtr; if (tree->count == 0) tree->root = newPtr; else _insert(tree, tree->root, newPtr); (tree->count)++; return true; } Data Structure
3. BST ADT • Internal Insert BST NODE* _insert (BST_TREE* tree, NODE* root, NODE* newPtr) { if (!root) // Base Case return newPtr; // root가 null 이면 return 되는 것은 newPtr if (tree->compare(newPtr->dataPtr, root->dataPtr) < 0) { root->left = _insert(tree, root->left, newPtr); } else { root->right = _insert(tree, root->right, newPtr); } return root; // root가 null 이 아닐때 return 되는 것은 단순히 root } 20 20 20 20 추가하려는 노드 추가하려는 노드 25 25 25 25 22 22 Data Structure
3. BST ADT • DeleteBST bool BST_Delete (BST_TREE* tree, void* dltKey) { bool success; NODE* newRoot; newRoot = _delete (tree, tree->root, dltKey, &success); if (success) { tree->root = newRoot; (tree->count)--; if (tree->count == 0) tree->root = NULL; } return success; } Data Structure
3. BST ADT • Internal DeleteBST NODE* _delete (BST_TREE* tree, NODE* root, void* dataPtr, bool* success) { NODE* dltPtr; // 삭제되어질 root 노드의 임시 저장소 NODE* exchPtr; // the largest nodeamong left subtree NODE* newRoot; // 삭제되어질 root 대신의 역할을 담당하게 될 노드 void* holdPtr; // 교환 작업을 위한 임시 저장소 if (!root) { // 삭제될 것이 검색이 안된 경우 *success = false; return NULL; } if (tree->compare(dataPtr, root->dataPtr) < 0) root->left = _delete (tree, root->left, dataPtr, success); else if (tree->compare(dataPtr, root->dataPtr) > 0) root->right = _delete (tree, root->right, dataPtr, success); Data Structure
3. BST ADT • Internal DeleteBST else { dltPtr = root; free (root->dataPtr); // data memory de-allocation if (!root->left) { // root의 왼쪽 자식이 null 이거나 // root 자체가 leaf 노드일 때 newRoot = root->right; free (dltPtr); *success = true; return newRoot; // base case } else if (!root->right) { // root의 왼쪽 자식은 null이 아니고 // root의 오른쪽 자식만 null일 때, newRoot = root->left; free (dltPtr); *success = true; return newRoot; // base case Case I Case II Case II Case I Case I Data Structure
3. BST ADT • Internal DeleteBST } else { // Find the lowest node on right subtree exchPtr = root->right; while (exchPtr->left) exchPtr = exchPtr->left; // Exchange Data holdPtr = root->dataPtr; root->dataPtr = exchPtr->dataPtr; exchPtr->dataPtr = holdPtr; // Deletethe largest node root->right = _delete (tree, root->right, exchPtr->dataPtr, success); } } return root; } Data Structure
3. BST ADT • RetrieveBST void* BST_Retrieve (BST_TREE* tree, void* keyPtr) { if (tree->root) return _retrieve (tree, keyPtr, tree->root); else return NULL; } void* _retrieve (BST_TREE* tree, void* dataPtr, NODE* root) { if (root) { if (tree->compare(dataPtr, root->dataPtr) < 0) return _retrieve(tree, dataPtr, root->left); else if (tree->compare(dataPtr, root->dataPtr) > 0) return _retrieve(tree, dataPtr, root->right); else return root->dataPtr; } else return NULL; } Data Structure
3. BST ADT • TraverseBST (inorder) void BST_Traverse (BST_TREE* tree, void (*process) (void* dataPtr)) { _traverse (tree->root, process); return; } void _traverse (NODE* root, void (*process) (void* dataPtr)) { if (root) { _traverse (root->left, process); process (root->dataPtr); _traverse (root->right, process); } return; } Data Structure
3. BST ADT • Empty, Full, Count BST bool BST_Empty (BST_TREE* tree) { return (tree->count == 0); } bool BST_Full (BST_TREE* tree) { NODE* newPtr; newPtr = (NODE*)malloc(sizeof (*(tree->root))); if (newPtr) { free (newPtr); return false; } else return true; } int BST_Count (BST_TREE* tree) { return (tree->count); } Data Structure
3. BST ADT • Destroy BST BST_TREE* BST_Destroy (BST_TREE* tree) { if (tree) _destroy (tree->root); free (tree); return NULL; } void _destroy (NODE* root) { if (root) { _destroy (root->left); free (root->dataPtr); _destroy (root->right); free (root); } return; } Data Structure
4. BST Application • Integer Application • BST Creation • reads integers from the keyboard and inserts them into the BST • reads integers from the keyboard and deletes them from the BST • If BST is empty, the application comes to the end Data Structure
4. BST Application • Integer Application (BST_INT.c) #include <stdio.h> #include <stdlib.h> #include "bst.h" #include "stdbool.h" int compareInt (void* num1, void* num2); void printBST (void* num1); int main (void) { BST_TREE* BSTRoot; int* dataPtr; int dataIn = 1; printf("Begin BST Demonstation\n"); BSTRoot = BST_Create (compareInt); printf("Enter a list of positive integers;\n"); printf("Enter a negative number to stop.\n"); Data Structure
4. BST Application • Integer Application (BST_INT.c) do { printf("Enter a number: "); scanf ("%d", &dataIn); if (dataIn > -1) { dataPtr = (int*) malloc (sizeof (int)); if (!dataPtr) { printf("Memory Overflow in add\n"); exit(100); } *dataPtr = dataIn; BST_Insert (BSTRoot, dataPtr); } } while (dataIn > -1); printf("\nBST contains:\n"); BST_Traverse (BSTRoot, printBST); Data Structure
4. BST Application • Integer Application (BST_INT.c) while (!BST_Empty(BSTRoot)) { printf("\nEnter an integers to be deleted;\n"); printf("Enter a number: "); scanf ("%d", &dataIn); if (!BST_Delete(BSTRoot, &dataIn)) printf("ERROR: No Number: $d\n", dataIn); printf("\nBST contains:\n"); BST_Traverse (BSTRoot, printBST); } printf("\nEnd BST Demonstration\n"); return 0; } Data Structure
4. BST Application • Integer Application (BST_INT.c) int compareInt (void* num1, void* num2) { int key1; int key2; key1 = *(int*)num1; key2 = *(int*)num2; if (key1 < key2) return -1; if (key1 == key2) return 0; return +1; } void printBST (void* num1) { printf("%4d\n", *(int*)num1); return; } Data Structure