当前位置:   article > 正文

【数据结构】(C语言):二叉搜索树

【数据结构】(C语言):二叉搜索树

二叉搜索树

  • 树不是线性的,是层级结构。
  • 基本单位是节点,每个节点最多2个子节点。
  • 有序。每个节点,其左子节点都比它小,其右子节点都比它大。
  • 每个子树都是一个二叉搜索树。每个节点及其所有子节点形成子树。
  • 可以是空树。

添加元素:从根节点开始,比对数值。若比它小,往左子树比对;若比它大,往右子树比对;直到找到为空,则为新元素的位置。

删除元素

  1. 若删除的节点为叶子节点(即无子节点),则直接删除。
  2. 若删除的节点只有左子节点,则左子节点替代删除节点。
  3. 若删除的节点只有右子节点,则右子节点替代删除节点。
  4. 若删除的节点既有左子节点又有右子节点,则找到直接前驱(即删除节点的左子树中的最大值,即删除节点的左子节点的最右节点),直接前驱的值替代删除节点的值,删除直接前驱节点。

清空树:从根节点开始遍历,依次从叶子节点开始 释放每个节点的内存空间,最终根节点指向NULL。

遍历元素:(可使用递归)

  • 前序遍历(顺序:根节点、左子节点、右子节点)。
  • 中序遍历(顺序:左子节点、根节点、右子节点)。
  • 后序遍历(顺序:左子节点、右子节点、根节点)。

查找元素:从根节点开始,比对数值。若比它小,往左子树查找;若比它大,往右子树查找;直到找到该元素,则返回1(true),若没有,则返回0(false)。


C语言实现:(使用链表实现)

 创建结构体数据类型(记录二叉搜索树的根节点和数据个数):

  1. typedef struct Link
  2. {
  3. LinkNode *root; // 根节点
  4. int length; // 统计有多少数据
  5. } LinkBST; // 别名

创建二叉搜索树,并初始化:

  1. LinkBST bst;
  2. bst.root = NULL; // 根节点,初始化为NULL
  3. bst.length = 0; // 数据个数,初始化为0

创建节点(结构体数据类型),并创建具体节点实例的函数:

  1. // 节点(结构体数据类型)
  2. typedef struct Node
  3. {
  4. int value; // 数据类型为整型
  5. struct Node *left; // 左子节点
  6. struct Node *right; // 右子节点
  7. }LinkNode; // 别名
  1. // 函数:创建节点
  2. LinkNode *createNode(int data)
  3. {
  4. LinkNode *node = (LinkNode *)malloc(sizeof(LinkNode)); // 分配节点内存空间
  5. if(node == NULL)
  6. {
  7. perror("Memory allocation failed");
  8. exit(-1);
  9. }
  10. node->value = data; // 数据
  11. node->left = NULL; // 左子节点,初始化为NULL
  12. node->right = NULL; // 右子节点,初始化为NULL
  13. return node;
  14. }

添加元素:

  1. void add(LinkBST *bst, int data) // add element
  2. {
  3. // 函数:往二叉搜索树中添加元素
  4. LinkNode *addNode(LinkNode *node, int data)
  5. {
  6. if(node == NULL)
  7. {
  8. LinkNode *newnode = createNode(data);
  9. node = newnode;
  10. bst->length++; // 每添加一个元素,length+1
  11. return node;
  12. }
  13. if(data < node->value) node->left = addNode(node->left, data);
  14. else if(data > node->value) node->right = addNode(node->right, data);
  15. return node;
  16. }
  17. // 从根节点开始比对,root指针始终指向二叉搜索树的根节点
  18. bst->root = addNode(bst->root, data);
  19. }

删除元素:

  1. void delete(LinkBST *bst, int data) // delete element
  2. {
  3. // 函数:删除节点
  4. LinkNode *del(LinkNode *node)
  5. {
  6. // 若只有右子节点,则右子节点替代删除节点
  7. if(node->left == NULL)
  8. {
  9. bst->length--; // 每删除一个元素,length-1
  10. return node->right;
  11. }
  12. // 若只有左子节点,则左子节点替代删除节点
  13. else if(node->right == NULL)
  14. {
  15. bst->length--; // 每删除一个元素,length-1
  16. return node->left;
  17. }
  18. // 左右子节点都有,则直接前驱(左子节点的最右节点)替代删除节点,并删除直接前驱
  19. else if(node->left && node->right)
  20. {
  21. LinkNode *tmp = node, *cur = node->left;
  22. while(cur->right)
  23. {
  24. tmp = cur;
  25. cur = cur->right;
  26. }
  27. node->value = cur->value;
  28. if(tmp != node) tmp->right = cur->left;
  29. else tmp->left = cur->left;
  30. bst->length--; // 每删除一个元素,length-1
  31. return node;
  32. }
  33. }
  34. // 函数:找到将要删除的节点
  35. LinkNode *delNode(LinkNode *node, int data)
  36. {
  37. if(node == NULL) return node;
  38. if(data == node->value) node = del(node);
  39. else if(data < node->value) node->left = delNode(node->left, data);
  40. else if(data > node->value) node->right = delNode(node->right, data);
  41. return node;
  42. }
  43. // 从根节点开始比对。root指针始终指向二叉搜索树的根节点
  44. bst->root = delNode(bst->root, data);
  45. }

清空树:

  1. void clear(LinkBST *bst)
  2. {
  3. // 函数:释放每个节点的内存空间
  4. void clearNode(LinkNode *node)
  5. {
  6. if(node->left == NULL && node->right == NULL)
  7. {
  8. free(node); // 使用malloc动态分配内存空间,不使用时需使用free释放内存空间
  9. node == NULL; // 释放内存空间后,指针指向NULL,避免野指针
  10. return ;
  11. }
  12. if(node->left) clearNode(node->left);
  13. if(node->right) clearNode(node->right);
  14. }
  15. // 树非空,释放所有节点的内存空间,根节点为NULL,数据个数为0
  16. if(bst->root == NULL) return ;
  17. clearNode(bst->root); // 从根节点开始遍历,依次从叶子节点开始释放内存空间
  18. bst->root = NULL; // 根节点指向NULL
  19. bst->length = 0; // 数据个数为0
  20. }

遍历元素:(使用递归)

  1. // 前序遍历(根,左,右)
  2. void pretravel(LinkNode *node)
  3. {
  4. if(node == NULL) return ;
  5. printf("%d ", node->value);
  6. pretravel(node->left);
  7. pretravel(node->right);
  8. }
  1. // 中序遍历(左,根,右)
  2. void midtravel(LinkNode *node)
  3. {
  4. if(node == NULL) return ;
  5. midtravel(node->left);
  6. printf("%d ", node->value);
  7. midtravel(node->right);
  8. }
  1. // 后序遍历(左,右,根)
  2. void posttravel(LinkNode *node)
  3. {
  4. if(node == NULL) return ;
  5. posttravel(node->left);
  6. posttravel(node->right);
  7. printf("%d ", node->value);
  8. }

查找元素:

找到元素,返回1(true);没找到,返回0(false)。

  1. int find(LinkNode *node, int data)
  2. {
  3. if(node == NULL) return 0;
  4. if(data == node->value) return 1;
  5. if(data < node->value) find(node->left, data);
  6. else if(data > node->value) find(node->right, data);
  7. }


完整代码:(bst.c)

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <stdbool.h>
  4. /* structure */
  5. typedef struct Node // linkedlist node
  6. {
  7. int value; // value type is integer
  8. struct Node *left; // left child node
  9. struct Node *right; // right child node
  10. }LinkNode;
  11. typedef struct Link // binary search tree
  12. {
  13. LinkNode *root; // root node of the tree
  14. int length; // the number of the tree
  15. } LinkBST;
  16. /* function prototype */
  17. void add(LinkBST *, int); // add element to the tree
  18. void delete(LinkBST *, int); // delete element from the tree
  19. void clear(LinkBST *); // clear the tree
  20. void pretravel(LinkNode *); // show element one by one,(root,left,right)
  21. void midtravel(LinkNode *); // show element one by one,(left,root,right)
  22. void posttravel(LinkNode *); // show element one by one,(left,right,root)
  23. int find(LinkNode *, int); // if find data,return 1(true),or return 0(false)
  24. /* main function */
  25. int main(void)
  26. {
  27. // create binary search tree and initialization
  28. LinkBST bst;
  29. bst.root = NULL;
  30. bst.length = 0;
  31. printf("isempty(1:true, 0:false): %d, length is %d\n", bst.root==NULL, bst.length);
  32. add(&bst, 15);
  33. add(&bst, 8);
  34. add(&bst, 23);
  35. add(&bst, 10);
  36. add(&bst, 12);
  37. add(&bst, 19);
  38. add(&bst, 6);
  39. printf("isempty(1:true, 0:false): %d, length is %d\n", bst.root==NULL, bst.length);
  40. printf("midtravel: ");
  41. midtravel(bst.root);
  42. printf("\n");
  43. printf("pretravel: ");
  44. pretravel(bst.root);
  45. printf("\n");
  46. printf("posttravel: ");
  47. posttravel(bst.root);
  48. printf("\n");
  49. printf("find 10 (1:true, 0:false): %d\n", find(bst.root, 10));
  50. printf("find 9 (1:true, 0:false): %d\n", find(bst.root, 9));
  51. delete(&bst, 23);
  52. delete(&bst, 15);
  53. delete(&bst, 6);
  54. printf("isempty(1:true, 0:false): %d, length is %d\n", bst.root==NULL, bst.length);
  55. printf("midtravel: ");
  56. midtravel(bst.root);
  57. printf("\n");
  58. printf("pretravel: ");
  59. pretravel(bst.root);
  60. printf("\n");
  61. printf("posttravel: ");
  62. posttravel(bst.root);
  63. printf("\n");
  64. clear(&bst);
  65. printf("isempty(1:true, 0:false): %d, length is %d\n", bst.root==NULL, bst.length);
  66. return 0;
  67. }
  68. /* subfunction */
  69. LinkNode *createNode(int data) // create a node
  70. {
  71. LinkNode *node = (LinkNode *)malloc(sizeof(LinkNode));
  72. if(node == NULL)
  73. {
  74. perror("Memory allocation failed");
  75. exit(-1);
  76. }
  77. node->value = data;
  78. node->left = NULL;
  79. node->right = NULL;
  80. return node;
  81. }
  82. void add(LinkBST *bst, int data) // add element
  83. {
  84. // subfunction(recursion): add element to the binary search tree
  85. LinkNode *addNode(LinkNode *node, int data)
  86. {
  87. if(node == NULL)
  88. {
  89. LinkNode *newnode = createNode(data);
  90. node = newnode;
  91. bst->length++;
  92. return node;
  93. }
  94. if(data < node->value) node->left = addNode(node->left, data);
  95. else if(data > node->value) node->right = addNode(node->right, data);
  96. return node;
  97. }
  98. // root node receive the result
  99. bst->root = addNode(bst->root, data);
  100. }
  101. void delete(LinkBST *bst, int data) // delete element
  102. {
  103. // subfunction(recursion): delete element from the binary search tree
  104. LinkNode *del(LinkNode *node)
  105. {
  106. if(node->left == NULL)
  107. {
  108. bst->length--;
  109. return node->right;
  110. }
  111. else if(node->right == NULL)
  112. {
  113. bst->length--;
  114. return node->left;
  115. }
  116. else if(node->left && node->right)
  117. {
  118. LinkNode *tmp = node, *cur = node->left;
  119. while(cur->right)
  120. {
  121. tmp = cur;
  122. cur = cur->right;
  123. }
  124. node->value = cur->value;
  125. if(tmp != node) tmp->right = cur->left;
  126. else tmp->left = cur->left;
  127. bst->length--;
  128. return node;
  129. }
  130. }
  131. // subfunction: find delete node,return node
  132. LinkNode *delNode(LinkNode *node, int data)
  133. {
  134. if(node == NULL) return node;
  135. if(data == node->value) node = del(node);
  136. else if(data < node->value) node->left = delNode(node->left, data);
  137. else if(data > node->value) node->right = delNode(node->right, data);
  138. return node;
  139. }
  140. // root node receive the result
  141. bst->root = delNode(bst->root, data);
  142. }
  143. void clear(LinkBST *bst) // clear the tree
  144. {
  145. // function: free memory space on ecah node
  146. void clearNode(LinkNode *node)
  147. {
  148. if(node->left == NULL && node->right == NULL)
  149. {
  150. free(node);
  151. node == NULL;
  152. return ;
  153. }
  154. if(node->left) clearNode(node->left);
  155. if(node->right) clearNode(node->right);
  156. }
  157. // if not empty tree,free memory space on each node,root is NULL and length is 0
  158. if(bst->root == NULL) return ;
  159. clearNode(bst->root);
  160. bst->root = NULL;
  161. bst->length = 0;
  162. }
  163. void pretravel(LinkNode *node) // show element one by one,(root,left,right)
  164. {
  165. if(node == NULL) return ;
  166. printf("%d ", node->value);
  167. pretravel(node->left);
  168. pretravel(node->right);
  169. }
  170. void midtravel(LinkNode *node) // show element one by one,(left,root,right)
  171. {
  172. if(node == NULL) return ;
  173. midtravel(node->left);
  174. printf("%d ", node->value);
  175. midtravel(node->right);
  176. }
  177. void posttravel(LinkNode *node) // show element one by one,(left,right,root)
  178. {
  179. if(node == NULL) return ;
  180. posttravel(node->left);
  181. posttravel(node->right);
  182. printf("%d ", node->value);
  183. }
  184. int find(LinkNode *node, int data) // if find data,return 1(true),or return 0(false)
  185. {
  186. if(node == NULL) return 0;
  187. if(data == node->value) return 1;
  188. if(data < node->value) find(node->left, data);
  189. else if(data > node->value) find(node->right, data);
  190. }

编译链接: gcc -o bst bst.c

执行可执行文件: ./bst

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/秋刀鱼在做梦/article/detail/777214
推荐阅读
相关标签
  

闽ICP备14008679号