当前位置:   article > 正文

数据结构-二叉排序树(建立、查找、修改)_数据结构二叉排序树创建

数据结构二叉排序树创建

二叉排序树概念

二叉排序树是动态查找表的一种,也是常用的表示方法。

其中,它具有如下性质:

1.若它的左子树非空,则其左子树的所有节点的关键值都小于根节点的关键值。

2.若它的右子树非空,则其右子树的所有节点的关键值都大于根结点的关键值。

3.它的左右子树也分别都是二叉排序树。

PS:对二叉排序树进行中序遍历,得到的序列,总会是一个升序的数列。

二叉排序树的建立

我们使用C语言来建立。

其中我们对二叉排序树的结构体定义如下:

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

建立二叉排序树的代码如下:

  1. BSTree InsertBST(BSTree bst,BSTree s) //遍历二叉排序树,找到合适的位置
  2. {
  3. if(bst==NULL)
  4. bst = s;
  5. else{
  6. if(s->key < bst->key)
  7. bst->lchild = InsertBST(bst->lchild,s);
  8. if(s->key > bst->key){
  9. bst->rchild = InsertBST(bst->rchild,s);
  10. }
  11. }
  12. return bst;
  13. }
  14. BSTree CreateBST() //建立二叉排序树
  15. {
  16. BSTree bst,s;
  17. int key;
  18. bst = NULL;
  19. printf("请输入关键字值,输入-1结束.\n");
  20. while(1){
  21. scanf("%d",&key);
  22. if(key!=-1){
  23. s = (BSTree)malloc(sizeof(BTNode));
  24. s->key = key;
  25. s->lchild = NULL;
  26. s->rchild = NULL;
  27. bst = InsertBST(bst,s);
  28. printf("成功.\n");
  29. }
  30. else
  31. break;
  32. }
  33. return bst;
  34. }

二叉排序树的插入

  1. BSTree InsertBST(BSTree bst,BSTree s) //遍历二叉排序树,找到合适的位置
  2. {
  3. if(bst==NULL)
  4. bst = s;
  5. else{
  6. if(s->key < bst->key)
  7. bst->lchild = InsertBST(bst->lchild,s);
  8. if(s->key > bst->key){
  9. bst->rchild = InsertBST(bst->rchild,s);
  10. }
  11. }
  12. return bst;
  13. }
  14. BSTree SearchBST(BSTree bst,int key) //查找关键值key的节点,并且返回这个节点
  15. {
  16. if(bst == NULL)
  17. return NULL;
  18. else if(key == bst->key)
  19. return bst;
  20. else if(key > bst->key)
  21. return SearchBST(bst->rchild,key);
  22. else
  23. return SearchBST(bst->lchild,key);
  24. }
  25. BSTree InsertBST_key(BSTree bst,int key) //搜寻一个关键值,如果没有就插入
  26. {
  27. BSTree s;
  28. s = SearchBST(bst,key);
  29. if(s)
  30. printf("该节点已经存在.");
  31. else{
  32. s = (BSTree)malloc(sizeof(BTNode));
  33. s->key = key;
  34. s->lchild = NULL;
  35. s->rchild = NULL;
  36. s = InsertBST(bst,s);
  37. }
  38. return s;
  39. }

查找二叉排序树指定节点的双亲

  1. BSTree SearchBST_F(BSTree bst,int key,BSTree *F) //F存储key关键值节点的双亲节点,函数返回key关键值节点.
  2. {
  3. if(bst == NULL)
  4. return NULL;
  5. if(key == bst->key)
  6. return bst;
  7. else{
  8. *F = bst;
  9. if(key < bst->key)
  10. return SearchBST_F(bst->lchild,key,F);
  11. else
  12. return SearchBST_F(bst->rchild,key,F);
  13. }
  14. }

 删除二叉排序树中某个节点:

对于删除二叉排序树的节点,我们有必要花大功夫来讨论一下。

对于删除二叉排序树的某个节点,大致有以下四种情况:

假设我们要删除的节点指定为P

1.P节点的左右子树都为空

此时删除P节点,只需要P节点的父节点的左/右子树赋值NULL,并且free掉P节点即可。

值得注意的是,还有一种特殊情况,那就是P节点本身就是根节点,也就是这个树只有P节点一个

节点。

那么此时,我们只需要返回NULL,并且free掉P节点即可。

2.P节点的左子树为空

在这种情况下,我们注意到P的右子树不是空的,如下图所示:

此时我们只需要令P节点的父节点C的右子树/左子树为P的右子树即可。

不过值得注意的是,此时仍有可能P是根节点,此时我们需要令根节点 = p的右子树,并且free掉p

节点即可。

3.P节点的右子树为空

此时我们注意到,这种情况根情况2(P节点的左子树为空)非常相似。

此时我们只需要令P的父节点C的左/右子树等于P的左子树即可。

不过此时P节点仍有可能作为根节点出现,此时我们只需要令根节点等于P的左子树即可。

4.P节点的左右子树都不为空

这种情况无疑是最复杂的一种情况,因为此时我们要牵扯一个大小的排序。

因此,我们可以令P节点的Key值等于P节点的直接前驱(直接后驱)的Key值,之后删掉直接前驱(直

接后驱)即可。

注意到此时的P节点的直接前驱是G(即P节点的左子树的最右侧的一个节点)。

那么此时我们可以令P节点的Key值等于G节点的Key值,同时free掉G节点即可完成操作。

不过,比较重要的一点是,G节点的左子树不一定为空此时我们仍需要让G节点的节点的右子

等于G节点的左子树

注意到,当P节点作为根结点的时候并不会出现特殊的情况,但是当P节点的前驱节点就是P的左子

,我们需要另外的讨论,如下图所示:

注意到此时P的直接前驱节点就是D,但是如果我们直接删除D,那么D的左子树此时应该给P的

子树。

注意到P也是D的一个父节点,P同时还是D的一个直接后继节点,此时就是一种特殊情况,需要让

P左子树等于D左子树,而不是D父节点右子树等于D左子树!!!

代码实现:

  1. BSTree SearchBST_F(BSTree bst,int key,BSTree *F) //查找Key值节点的父节点,*F存储父节点,函数返回Key节点
  2. {
  3. if(bst == NULL)
  4. return NULL;
  5. if(bst->key == key)
  6. return bst;
  7. else{
  8. *F = bst;
  9. if(bst->key > key)
  10. return SearchBST_F(bst->lchild,key,F);
  11. else
  12. return SearchBST_F(bst->rchild,key,F);
  13. }
  14. }
  15. BSTree DeleteBST(BSTree bst,BSTree p,BSTree f)
  16. {
  17. BSTree par,s;
  18. int kind;
  19. if(!p->lchild && !p->rchild) //左右子树全为空
  20. kind = 1;
  21. else if(!p->lchild) //左子树为空
  22. kind = 2;
  23. else if(!p->rchild) //右子树为空
  24. kind = 3;
  25. else //左右子树都不为空
  26. kind = 4;
  27. switch(kind){
  28. case 1:
  29. if(!f) //没有父节点,p是根节点,
  30. return NULL;
  31. else{
  32. if(f->lchild == p)
  33. f->lchild = NULL;
  34. else
  35. f->rchild = NULL;
  36. free(p);
  37. }
  38. break;
  39. case 2:
  40. if(!f) //p是根节点
  41. bst = bst->rchild;
  42. else{
  43. if(p == f->lchild)
  44. f->lchild = p->rchild;
  45. else
  46. f->rchild = p->rchild;
  47. free(p);
  48. }
  49. break;
  50. case 3:
  51. if(!f) //p是根节点
  52. bst = bst->lchild;
  53. else{
  54. if(p == f->lchild)
  55. f->lchild = bst->lchild;
  56. else
  57. f->rchild = bst->lchild;
  58. }
  59. free(p);
  60. break;
  61. case 4:
  62. par = p; //p节点前驱指针par
  63. s = p->lchild; //用来遍历p的直接前驱节点(左子树的最右侧)
  64. while(s->rchild != NULL){ //结束条件是s的右子树为空,此时s就是p的直接前驱节点
  65. par = s;
  66. s = s->rchild;
  67. }
  68. p->key = s->key; //令p节点的值为s节点的值
  69. if(par == p) //特殊情况,s节点刚好是p的左子树
  70. par->lchild = s->lchild;
  71. else
  72. par->rchild = s->lchild; //par的右子树需要等于s节点的左子树
  73. free(s); //释放p节点的直接前驱s
  74. break;
  75. }
  76. return bst;
  77. }
  78. BSTree SearchDeleteBST(BSTree bst,int key)
  79. {
  80. BSTree f = NULL,p;
  81. p = SearchBST_F(bst,key,&f);
  82. if(p){
  83. bst = DeleteBST(bst,p,f);
  84. }
  85. else
  86. printf("该节点不存在.\n");
  87. return bst;
  88. }

二叉排序树的所有代码汇总: 

  1. #include<stdio.h>
  2. #include<malloc.h>
  3. typedef int ElemType;
  4. typedef struct BSNode{
  5. ElemType key;
  6. struct BSNode *lchild,*rchild;
  7. }BSNode,*BSTree;
  8. BSTree SearchBST(BSTree bst,BSTree s)
  9. {
  10. if(bst == NULL)
  11. bst = s;
  12. else{
  13. if(bst->key > s->key)
  14. bst->lchild = SearchBST(bst->lchild,s);
  15. if(bst->key < s->key)
  16. bst->rchild = SearchBST(bst->rchild,s);
  17. }
  18. return bst;
  19. }
  20. BSTree CreateBSTree()
  21. {
  22. int key;
  23. BSTree bst = NULL;
  24. printf("请输入节点关键值,输入-1结束.\n");
  25. while(1){
  26. scanf("%d",&key);
  27. if(key != -1){
  28. BSTree s = (BSTree)malloc(sizeof(BSNode));
  29. s->key = key;
  30. s->lchild = NULL;
  31. s->rchild = NULL;
  32. bst = SearchBST(bst,s);
  33. printf("创建节点成功.\n");
  34. }
  35. else
  36. break;
  37. }
  38. return bst;
  39. }
  40. void PostTraverse(BSTree bst)
  41. {
  42. if(bst){
  43. PostTraverse(bst->lchild);
  44. printf("%d ",bst->key);
  45. PostTraverse(bst->rchild);
  46. }
  47. }
  48. BSTree SearchBST_F(BSTree bst,int key,BSTree *F) //查找Key值节点的父节点,*F存储父节点,函数返回Key节点
  49. {
  50. if(bst == NULL)
  51. return NULL;
  52. if(bst->key == key)
  53. return bst;
  54. else{
  55. *F = bst;
  56. if(bst->key > key)
  57. return SearchBST_F(bst->lchild,key,F);
  58. else
  59. return SearchBST_F(bst->rchild,key,F);
  60. }
  61. }
  62. BSTree DeleteBST(BSTree bst,BSTree p,BSTree f)
  63. {
  64. BSTree par,s;
  65. int kind;
  66. if(!p->lchild && !p->rchild) //左右子树全为空
  67. kind = 1;
  68. else if(!p->lchild) //左子树为空
  69. kind = 2;
  70. else if(!p->rchild) //右子树为空
  71. kind = 3;
  72. else //左右子树都不为空
  73. kind = 4;
  74. switch(kind){
  75. case 1:
  76. if(!f) //没有父节点,p是根节点,
  77. return NULL;
  78. else{
  79. if(f->lchild == p)
  80. f->lchild = NULL;
  81. else
  82. f->rchild = NULL;
  83. free(p);
  84. }
  85. break;
  86. case 2:
  87. if(!f) //p是根节点
  88. bst = bst->rchild;
  89. else{
  90. if(p == f->lchild)
  91. f->lchild = p->rchild;
  92. else
  93. f->rchild = p->rchild;
  94. free(p);
  95. }
  96. break;
  97. case 3:
  98. if(!f) //p是根节点
  99. bst = bst->lchild;
  100. else{
  101. if(p == f->lchild)
  102. f->lchild = bst->lchild;
  103. else
  104. f->rchild = bst->lchild;
  105. }
  106. free(p);
  107. break;
  108. case 4:
  109. par = p; //p节点前驱指针par
  110. s = p->lchild; //用来遍历p的直接前驱节点(左子树的最右侧)
  111. while(s->rchild != NULL){ //结束条件是s的右子树为空,此时s就是p的直接前驱节点
  112. par = s;
  113. s = s->rchild;
  114. }
  115. p->key = s->key; //令p节点的值为s节点的值
  116. if(par == p) //特殊情况,s节点刚好是p的左子树
  117. par->lchild = s->lchild;
  118. else
  119. par->rchild = s->lchild; //par的右子树需要等于s节点的左子树
  120. free(s); //释放p节点的直接前驱s
  121. break;
  122. }
  123. return bst;
  124. }
  125. BSTree SearchDeleteBST(BSTree bst,int key)
  126. {
  127. BSTree f = NULL,p;
  128. p = SearchBST_F(bst,key,&f);
  129. if(p){
  130. bst = DeleteBST(bst,p,f);
  131. }
  132. else
  133. printf("该节点不存在.\n");
  134. return bst;
  135. }
  136. int main()
  137. {
  138. BSTree bst;
  139. bst = CreateBSTree();
  140. SearchDeleteBST(bst,5);
  141. PostTraverse(bst);
  142. return 0;
  143. }
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/不正经/article/detail/709661
推荐阅读
相关标签
  

闽ICP备14008679号