当前位置:   article > 正文

二叉排序树详解以及实现_二叉排序树的构造过程

二叉排序树的构造过程

目录

1.二叉排序树概念

2.二叉排序树的插入

(1)二叉排序树的插入过程

(2)节点插入实现

3.二叉排序树的查找

4.二叉排序树的遍历

5.二叉树排序树节点的删除

(1)删除二叉排序树节点*P

6.完整的流程测试


使用C语言实现二叉树的链式存储

数据结构之折半查找(递归和非递归),插值查找和斐波那契查找

静态树表的查找(最优查找树和次优查找树)

1.二叉排序树概念

二叉排序树(Binary Sort Tree)也称为二叉查找树后者二叉搜索树

  • 具有的性质:
    • 1.若它的左子树不空,则左子树上的所有节点的值均小于它的根节点的值;
    • 2.若它的右子树不空,则右子树上的所有节点的值均大于它的根节点的值;
    • 3.若左右子树都不为空,左右子树也分别为二叉排序树;

二叉排序树结构的定义:

  1. typedef int ElemType;
  2. typedef struct BSTNode{
  3. ElemType data;
  4. struct BSTNode*lchild,*rchild;
  5. }*BSTree;

2.二叉排序树的插入

(1)二叉排序树的插入过程

假设:现在有查找的关键字序列为{45,24,53,45,12,24,90},二叉排序树的插入过程如下:

(2)节点插入实现

  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. #include<string.h>
  4. #include<queue>
  5. #include<stack>
  6. void BSTreemenu(){
  7. printf("---------------1.插入节点--------------\n");
  8. printf("---------------2.查询节点--------------\n");
  9. printf("---------------3.删除节点--------------\n");
  10. printf("---------------4.输出节点--------------\n");
  11. printf("---------------5.退出程序--------------\n");
  12. }
  1. //构造一棵二叉排序树
  2. int BST_Insert(BSTree&T,int key){
  3. if(T==NULL){
  4. T=(BSTree)malloc(sizeof(BSTNode));
  5. T->data=key;
  6. T->lchild=NULL;
  7. T->rchild=NULL;
  8. return 1;
  9. }else if(T->data==key){
  10. return 0;
  11. }else if(T->data>key){
  12. BST_Insert(T->lchild,key);
  13. }else {
  14. BST_Insert(T->rchild,key);
  15. }
  16. }

3.二叉排序树的查找

二叉排序树的查找过程类似于次优二叉树,查找步骤:

  • 1.首先将给定值和根节点的值进行比较,若相等,则查找成功,否则进行第二步;
  • 2.若给定的值大于根节点的值,则到根节点的右子树上进行相同的比较;
  • 3.若给定的值小于根节点的值,则到根节点的左子树上进行相同的比较;
  1. //递归查询节点
  2. BSTNode*BST_Search(BSTree T,int key){
  3. if(T==NULL)return NULL;
  4. if(T->data==key){
  5. return T;
  6. }else if(T->data>key){
  7. BST_Search(T->lchild,key);
  8. }else{
  9. BST_Search(T->rchild,key);
  10. }
  11. }
  12. //非递归查询
  13. BSTNode*BSTSearch(BSTree T,int key){
  14. while(T!=NULL&&T->data!=key){
  15. if(T->data>key){
  16. T=T->lchild;
  17. }else{
  18. T=T->rchild;
  19. }
  20. }
  21. }

4.二叉排序树的遍历

该遍历和二叉树的遍历过程一样,但是这里有一个技巧,就是判断一棵二叉树是否为二叉排序树:如果中序遍历为有序的序列,则为二叉排序树。

  1. //中序遍历二叉排序树(有序)
  2. void BST_display(BSTree T){
  3. if(T==NULL)return;
  4. BST_display(T->lchild);
  5. printf("%d ",T->data);
  6. BST_display(T->rchild);
  7. }

5.二叉树排序树节点的删除

(1)删除二叉排序树节点*P

  • 情况一:
    • 如果*P节点为叶子节点,那么其左右子树都是为NULL,也就是删除此节点并不会破坏整棵树的结构,所以直接删除节点*P即可。

 

 

  • 情况二:
    • 如果*P节点只有左子树PL或者右子树PR,那么只需要将PL或者PR为*P双亲*F的左子树或者右子树即可。

 

  • 情况三:
    • 如果左右子树都不为空的话,那么以上方法则不能使用。由于二叉排序树中序遍历时得到是一个从小到大的序列,在删除节点*P之前,首先找到其*P的直接前驱*S(也就是*P的左子树上最大值的节点)或者直接后继*S(也就是*P右子树上最小值的节点),使用直接前驱或者直接后继的值替代*P节点的值。注意:虽然使用直接前驱或者直接后继的值去替代之后,还是不能直接删除直接前驱或者直接后继,因为对于直接前驱节点来说,有可能其左子树不为空;而对于直接后继节点来说,有可能其右子树不为空,对于上面这种情况的话,使用直接前驱或者直接后继替代*P之后,我们需要将*S的左子树或者右子树挂到*S的双亲节点上去。

 

  1. //删除节点操作
  2. //情况一
  3. void DeleteBSTOne(BSTree T,int key){
  4. if(!T){
  5. printf("不存在删除的节点!\n");
  6. }else{
  7. if(T->data==key){
  8. free(T);
  9. printf("删除成功!\n");
  10. }else if(T->data>key){
  11. DeleteBSTOne(T->lchild,key);
  12. }else{
  13. DeleteBSTOne(T->rchild,key);
  14. }
  15. }
  16. }
  17. //情况二,三
  18. void DeleteBSTwoThree(BSTNode*p){
  19. //如果*p不存在右子树,那么只需要将左子树挂到双亲上
  20. BSTNode*q=NULL;
  21. if(!p->rchild){
  22. q=p;
  23. p=p->lchild;
  24. free(q);
  25. }else if(!p->lchild){//否则接右子树
  26. q=p;
  27. p=p->rchild;
  28. free(q);
  29. }else{//左右子树都不空情况
  30. q=p;
  31. BSTNode*s=p->lchild;
  32. //找到直接前驱,也就是*P左子树的最大值
  33. while(s->rchild){
  34. q=s;//q指向节点s的双亲
  35. s=s->rchild;
  36. }
  37. p->data=s->data;
  38. if(q!=p){
  39. q->rchild=s->lchild;
  40. }else{
  41. q->lchild=s->lchild;
  42. }
  43. free(s);
  44. }
  45. printf("删除节点成功!");
  46. return ;
  47. }

6.完整的流程测试

  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. #include<string.h>
  4. #include<queue>
  5. #include<stack>
  6. typedef int ElemType;
  7. typedef struct BSTNode{
  8. ElemType data;
  9. struct BSTNode*lchild,*rchild;
  10. }*BSTree;
  11. void BSTreemenu(){
  12. printf("---------------1.插入节点--------------\n");
  13. printf("---------------2.查询节点--------------\n");
  14. printf("---------------3.删除节点--------------\n");
  15. printf("---------------4.输出节点--------------\n");
  16. printf("---------------5.退出程序--------------\n");
  17. }
  18. //构造一棵二叉排序树
  19. int BST_Insert(BSTree&T,int key){
  20. if(T==NULL){
  21. T=(BSTree)malloc(sizeof(BSTNode));
  22. T->data=key;
  23. T->lchild=NULL;
  24. T->rchild=NULL;
  25. return 1;
  26. }else if(T->data==key){
  27. return 0;
  28. }else if(T->data>key){
  29. BST_Insert(T->lchild,key);
  30. }else {
  31. BST_Insert(T->rchild,key);
  32. }
  33. }
  34. //销毁操作
  35. void BST_Destroy(BSTree&T){
  36. if(T==NULL)return ;
  37. BST_Destroy(T->lchild);
  38. BST_Destroy(T->rchild);
  39. free(T);
  40. }
  41. //递归查询节点
  42. BSTNode*BST_Search(BSTree T,int key){
  43. if(T==NULL)return NULL;
  44. if(T->data==key){
  45. return T;
  46. }else if(T->data>key){
  47. BST_Search(T->lchild,key);
  48. }else{
  49. BST_Search(T->rchild,key);
  50. }
  51. }
  52. //非递归查询
  53. BSTNode*BSTSearch(BSTree T,int key){
  54. while(T!=NULL&&T->data!=key){
  55. if(T->data>key){
  56. T=T->lchild;
  57. }else{
  58. T=T->rchild;
  59. }
  60. }
  61. }
  62. //中序遍历二叉排序树(有序)
  63. void BST_display(BSTree T){
  64. if(T==NULL)return;
  65. BST_display(T->lchild);
  66. printf("%d ",T->data);
  67. BST_display(T->rchild);
  68. }
  69. //删除节点操作
  70. //情况一
  71. void DeleteBSTOne(BSTree T,int key){
  72. if(!T){
  73. printf("不存在删除的节点!\n");
  74. }else{
  75. if(T->data==key){
  76. free(T);
  77. printf("删除成功!\n");
  78. }else if(T->data>key){
  79. DeleteBSTOne(T->lchild,key);
  80. }else{
  81. DeleteBSTOne(T->rchild,key);
  82. }
  83. }
  84. }
  85. //情况二,三
  86. void DeleteBSTwoThree(BSTNode*p){
  87. //如果*p不存在右子树,那么只需要将左子树挂到双亲上
  88. BSTNode*q=NULL;
  89. if(!p->rchild){
  90. q=p;
  91. p=p->lchild;
  92. free(q);
  93. }else if(!p->lchild){//否则接右子树
  94. q=p;
  95. p=p->rchild;
  96. free(q);
  97. }else{//左右子树都不空情况
  98. q=p;
  99. BSTNode*s=p->lchild;
  100. //找到直接前驱,也就是*P左子树的最大值
  101. while(s->rchild){
  102. q=s;//q指向节点s的双亲
  103. s=s->rchild;
  104. }
  105. p->data=s->data;
  106. if(q!=p){
  107. q->rchild=s->lchild;
  108. }else{
  109. q->lchild=s->lchild;
  110. }
  111. free(s);
  112. }
  113. printf("删除节点成功!");
  114. return ;
  115. }
  116. int main(){
  117. BSTree T=NULL;
  118. int key;
  119. BSTNode*p;
  120. int flag;
  121. while(1){
  122. int opt;
  123. BSTreemenu();
  124. printf("请输入操作: ");
  125. scanf("%d",&opt);
  126. switch(opt){
  127. case 1:
  128. printf("请输入元素(end=-1): ");
  129. scanf("%d",&key);
  130. while(key!=-1){
  131. flag=BST_Insert(T,key);
  132. if(flag==0){
  133. printf("该元素已经存在\n");
  134. }
  135. printf("请输入元素(end=-1): ");
  136. scanf("%d",&key);
  137. }
  138. break;
  139. case 2:
  140. printf("请输入要查找的元素: ");
  141. scanf("%d",&key);
  142. p=BST_Search(T,key);
  143. if(p!=NULL){
  144. printf("查找的元素为: %d\n",p->data);
  145. }else{
  146. printf("查找的元素不存在\n");
  147. //不存在该元素,则插入
  148. BST_Insert(T,key);
  149. }
  150. break;
  151. case 3:
  152. //这里删除节点只操作了叶子节点,关于有左子树(或者右子树),左右子树都不空情况代码已经实现,读者可以
  153. //自己尝试
  154. printf("请输入删除节点的值: ");
  155. scanf("%d",&key);
  156. DeleteBSTOne(T,key);
  157. case 4:
  158. BST_display(T);
  159. printf("\n");
  160. break;
  161. default:
  162. flag=5;
  163. printf("退出操作:\n");
  164. BST_Destroy(T);
  165. break;
  166. }
  167. if(flag==5)break;
  168. }
  169. return 0;
  170. }

 

 

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

闽ICP备14008679号