문제
이진 탐색트리의 삽입, 삭제, 탐색, 순회 및 출력 기능을 바탕으로 학생의 이름과 전화번호를 관리하는 이진탐색트리를 구현하라.
풀이
각 기능을 수행하는 함수는 책에서 학습 할 수 있지만 삭제 함수의 경우, 제가 갖고있는 2권의 자료구조책에는 삭제함수를 반복문으로 구현했는데, 물론 기능적인 면에서 순환방식보다 빠르고 효율적이지만 코드가 복잡하고, 혼자서 머릿속으로 구현하기가 힘든 것 같아 순환방법의 구현을 공부했습니다.
구현 면에서는 반복문보다 순환호출이 더 이해와 구현이 쉬운 것 같습니다.
주의할 것은 삭제함수에 if문이 많은데 각 경우를 if로 표현하면 학생 정보를 삭제하고 출력 시 원하지 않는 결과가 나올 수 있습니다.
반드시 if~ else if ~ else 문으로 함수를 작성해야합니다.
그리고 가끔 이런 학생정보 관리 프로그램이나 사전 프로그램 등을 구현하다보면 꼭 공백이나 엔터키가 말썽을 부렸는데
다행히 아래 코드처럼 작성하니 엔터키 관련해서는 오류가 뜨지않았습니다.
133~134행을 주석 처리 후 135~136행을 작성 후 실행 하면 원하는 기능의 알파벳 입력 시 한글을 입력하면 엔터키 오류가 뜹니다.
코드
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 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 | // 이진 탐색 트리를 사용한 영어 사전 #pragma warning(disable:4996) #include <stdio.h> #include <stdlib.h> #include <string.h> #include <memory.h> #define MAX_WORD_SIZE 100 #define MAX_MEANING_SIZE 200 // 데이터 형식 typedef struct { char name[MAX_WORD_SIZE]; // 키필드 char number[MAX_MEANING_SIZE]; } element; // 노드의 구조 typedef struct TreeNode { element key; TreeNode* left, * right; } TreeNode; // 만약 e1 < e2 이면 -1 반환 // 만약 e1 == e2 이면 0 반환 // 만약 e1 > e2 이면 1 반환 int compare(element e1, element e2) { return strcmp(e1.name, e2.name); } // 이진 탐색 트리 출력 함수 void display(TreeNode* p) { if (p != NULL) { //printf("("); display(p->left); printf("이름:%s\n전화번호%s\n", p->key.name, p->key.number); display(p->right); //printf(")"); } } // 이진 탐색 트리 탐색 함수 TreeNode* search(TreeNode* root, element key) { TreeNode* p = root; while (p != NULL) { if (compare(key, p->key) == 0) return p; else if (compare(key, p->key) < 0) p = p->left; else if (compare(key, p->key) > 0) p = p->right; } return p; // 탐색에 실패했을 경우 NULL 반환 } TreeNode* new_node(element item) { TreeNode* temp = (TreeNode*)malloc(sizeof(TreeNode)); temp->key = item; temp->left = temp->right = NULL; return temp; } TreeNode* insert_node(TreeNode* node, element key) { // 트리가 공백이면 새로운 노드를 반환한다. if (node == NULL) return new_node(key); // 그렇지 않으면 순환적으로 트리를 내려간다. if (compare(key, node->key) < 0) node->left = insert_node(node->left, key); else if (compare(key, node->key) > 0) node->right = insert_node(node->right, key); // 루트 포인터를 반환한다. return node; } TreeNode* min_value_node(TreeNode* node) { TreeNode* current = node; // 맨 왼쪽 단말 노드를 찾으러 내려감 while (current->left != NULL) current = current->left; return current; } // 이진 탐색 트리와 키가 주어지면 키가 저장된 노드를 삭제하고 // 새로운 루트 노드를 반환한다. TreeNode* delete_node(TreeNode* root, element key) { if (root == NULL) return root; // 만약 키가 루트보다 작으면 왼쪽 서브 트리에 있는 것임 if (compare(key, root->key) < 0) root->left = delete_node(root->left, key); // 만약 키가 루트보다 크면 오른쪽 서브 트리에 있는 것임 else if (compare(key, root->key) > 0) root->right = delete_node(root->right, key); // 키가 루트와 같으면 이 노드를 삭제하면 됨 else { // 첫 번째나 두 번째 경우 if (root->left == NULL) { TreeNode* temp = root->right; free(root); return temp; } else if (root->right == NULL) { TreeNode* temp = root->left; free(root); return temp; } // 세 번째 경우 TreeNode* temp = min_value_node(root->right); // 중외 순회시 후계 노드를 복사한다. root->key = temp->key; // 중외 순회시 후계 노드를 삭제한다. root->right = delete_node(root->right, temp->key); } return root; } // void help() { printf("삽입(i), 탐색(s),프린트(p), 삭제(d): "); } // 이진 탐색 트리를 사용하는 영어 사전 프로그램 int main(void) { char command; element e; TreeNode* root = NULL; TreeNode* tmp; while(1){ help(); //command = getchar(); //getchar(); // 엔터키 제거 scanf(" %c", &command); getchar(); switch (command) { case 'i': printf("친구의 이름: "); scanf(" %s", e.name); getchar(); printf("친구의 전화번호: "); scanf(" %s", e.number); getchar(); root = insert_node(root, e); break; case 'd': printf("이름:"); scanf(" %s", e.name); getchar(); root = delete_node(root, e); break; case 'p': display(root); printf("\n"); break; case 's': printf("친구의 이름:"); scanf(" %s", e.name); getchar(); tmp = search(root, e); if (tmp != NULL) printf("%s의 전화번호:%s\n",tmp->key.name, tmp->key.number); else printf("데이터가 존재하지 않습니다.\n"); break; case 'q':return 0; default: printf("잘못입력습니다.재입력하세요\n"); } }/* while (command != 'q');*/ return 0; } | cs |
'과제 > 자료구조' 카테고리의 다른 글
#5. 단순연결리스트를 이용한 정렬리스트 만들기 (0) | 2020.04.22 |
---|---|
#4. 수식을 후위식으로 변환하고 계산하기 (2) | 2020.04.11 |
#3. 구조체,배열을 이용해 성적정렬하기 (6) | 2020.04.01 |
#2. 순환함수를 이용한 코드 완성 (0) | 2020.03.25 |
#1.수행시간을 측정해 결과값 제출 (0) | 2020.03.25 |