基于树的查找--------------二叉查找树

1,为什么要分析二叉查找树(又名:二叉排序树)?
           正真分析开源代码或软件开发中,基于树的查找是难免会有的,现在多用的是
红黑树,而红黑树是基于平衡树的,而平衡树是基于查找树的,而查找树是基于二叉
树的,二叉树大家都很熟悉,所以先从查找树开始分析。这样才便于分析平衡树,最终
的分析对象将会是红黑树。
——————————————————————————————-
2,什么是二叉查找树?
      递归定义如下:
           (1),若左子树不为空,则左子数上所有结点的值均小于根结点的值。
           (2),若右子树不为空,则右子数上所有结点的值均大于根结点的值。
           (3),它的左右子树也分别是二叉查找树。

下面就是一个二叉查找树,任何一个子树,都是右孩子最大,根节点其次,左孩子最小。
《基于树的查找--------------二叉查找树》

——————————————————————————————-
3,二叉查找树的建立。
      二叉查找树的创建和插入是联系在一起的,树的创建就是使用的插入方式。从一颗空树开始
不停地插入,直到称为一颗完整的树。
例如:

  1. 39 int create_bst(bstree**bst)
  2.  40 {
  3.  41 int a[]={24,12,53,28,45,90};
  4.  42 int length= ARRAY_SIZE(a);
  5.  43 int i = 0;
  6.  44
  7.  45 *bst = NULL;
  8.  46
  9.  47 for (i=0;i<length;i++){
  10.  48 insert_bstree(bst,a[i]);
  11.  49 }
  12.  50
  13.  51 return 0;
  14.  52 }

现在要创建一个6个节点的数,插入的顺序是24,12,53,28,45,90.
创建树的图示如下:
《基于树的查找--------------二叉查找树》
——————————————————————————————–
4,二叉查找树的插入。
实例代码:

  1. 20 void insert_bstree(bstree**root,int key)
  2.  21 {
  3.  22 if ((*root)==NULL) {
  4.  23 (*root)=(bstree *)malloc(sizeof(bstree));
  5.  24 if ((*root)==NULL)
  6.  25 printf(“file %s,line %d:malloc error\n”,__FILE__,__LINE__);
  7.  26 (*root)>key= key;
  8.  27 (*root)>lchild=NULL;
  9.  28 (*root)>rchild=NULL;
  10.  29 } else {
  11.  30 if (key ==(*root)>key){
  12.  31 ;
  13.  32 } else if (key<(*root)>key){
  14.  33 insert_bstree(&((*root)>lchild),key);
  15.  34 } else
  16.  35 insert_bstree(&((*root)>rchild),key);
  17.  36 }
  18.  37 }

该插入的地方只可能是叶子节点,所以这儿使用了一个递归,先要找到插入的位置,
如果key值小,则往左走,key值大则往右走,直到为空,然后才找到位置,创建节
点将节点插入其中。
————————————————————————————————————-
5,二叉查找树的删除。
二叉查找树的删除比较麻烦,因为删除一个节点后还要保证其仍然是一个二叉查找树。
现在根据要删除节点的类型将情况分为四类。
情况1:删除的节点为叶子节点。
《基于树的查找--------------二叉查找树》
例如,上面的树上有三个叶子,分别是12,45,90,无论删除那个节点仍然是二叉查找树,
故只需将该节点释放,然后将其父节点的指针域做一些“善后”工作即可。实现代码如下:

  1. case 1:
  2.        free(pnode);//释放节点。
  3.        if (father>lchild== pnode)//对其父节点做出指针域的善后工作。
  4.             father>lchild=NULL;
  5.         else
  6.             father>rchild=NULL;
  7.         goto out2;//退出

情况2:删除的节点有右子树没有左子树。

《基于树的查找--------------二叉查找树》
该情况也不算复杂,首先要考虑要删除的节点是否可能是根节点,如果是根节点,也好办,
因为这是一个只有“右半边”的查找树,直接把根给删了,根节点的右子树作为根节点。
如果要删除的节点不是根节点,也好办,如图中的28,直接将右子树交给自己的父亲
“照看”。实现代码如下:

  1. case 2:
  2.     if (father ==NULL){//如果要删除的节点为根节点情况。
  3.          *root= pnode>rchild;//将要删除节点的右子树作为新的根。
  4.           free(pnode);//释放要删除的节点。
  5.           goto out1;//退出。
  6.     }
  7.     if (father>lchild== pnode) //不是根节点的情况,
  8.          father>lchild= pnode>rchild;//如果删除的节点是父节点的左孩子,现在就吧自己的右子树作为
  9.     else                                //父节点的左孩子。
  10.           father>rchild= pnode>rchild;//如果删除的节点是父节点的右孩子,现在就把自己的右子树作为
  11.     free(pnode);                          //父节点的右孩子。
  12.     goto out2;//释放节点后退出

情况3:删除的节点有左子树没有右子树。
          该情况和情况2类似,故不作详细的分析了。
           实现代码如下:


  1. case 3:
  2.     if (father ==NULL){
  3.         *root= pnode>lchild;
  4.          free(pnode);
  5.          goto out1;
  6.      }
  7.      if (father>lchild== pnode)
  8.           father>lchild= pnode>lchild;
  9.      else
  10.            father>rchild= pnode>lchild;
  11.       free(pnode);
  12.       goto out2;

情况4:删除的节点有左子树有右子树。

《基于树的查找--------------二叉查找树》
该情况是这四种情况中最复杂的一种了,如何删除该节点后仍然保证其是二叉查找树呢。
例如上图的24和53.

算法思想如下:
<1>,找到要删除节点pnode的中序序列的直接前驱s。(53的就是45,24的就是12)
<2>,将pnode的左子树交给pnode的父亲“照顾”。
<3>,将pnode的右子树交给pnode的直接前驱S”照顾”。
经过以上的三步,就可以保证Pnode的左右子树各有“所养”。

算法实现代码如下:

  1. 132 case 4:
  2. 133 s = pnode>lchild;  //球pnode中序序列的直接前驱。
  3. 134 while (s>rchild)
  4. 135 s = s>rchild;        
  5. 136 if (father ==NULL){  //如果删除的节点是根节点
  6. 137 *root = pnode>lchild; //左子树成为新的根。
  7. 138 s>rchild= pnode>rchild;//右子树交给直接前驱S
  8. 139 free(pnode);
  9. 140 goto out2;
  10. 141 }
  11. 142 if (father>rchild== pnode){
  12. 143 father>rchild= pnode>lchild;//左子树交给父节点。
  13. 144 s>rchild= pnode>rchild;//右子树交给直接前驱S
  14. 145 free(pnode);
  15. 146 goto out2;
  16. 147 }else{
  17. 148 father>lchild= pnode>rchild;//左子树交给父节点。
  18. 149 s>lchild= pnode>lchild;//右子树交给直接前驱S
  19. 150 free(pnode);
  20. 151 goto out2;
  21. 152

———————————————————————————————
6,实例代码。(完整代码)
《基于树的查找--------------二叉查找树》 bstree.rar 

    原文作者:二叉查找树
    原文地址: https://blog.csdn.net/u010734727/article/details/40682171
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞