zoukankan      html  css  js  c++  java
  • 数据结构树之二分查找树

    二叉查找树Binary Search Tree),也称有序二叉树(ordered binary tree),排序二叉树(sorted binary tree),是指一棵空树或者具有下列性质的二叉树:

    1. 若任意节点的左子树不空,则左子树上所有结点的值均小于它的根结点的值;
    2. 任意节点的右子树不空,则右子树上所有结点的值均大于它的根结点的值;
    3. 任意节点的左、右子树也分别为二叉查找树。
    4. 没有键值相等的节点(no duplicate nodes)。

    二叉查找树的性质:

      二叉查找树本质上是一种二叉树,所以上章讲的二叉树的性质他都有。

    二叉查找树的思想:

      二叉排序树的查找过程和次优二叉树类似,通常采取二叉链表作为二叉排序树存储结构中序遍历二叉排序树可得到一个关键字的有序序列,一个无序序列可以通过构造一棵二叉排序树变成一个有序序列,构造树的过程即为对无序序列进行排序的过程。每次插入的新的结点都是二叉排序树上新的叶子结点,在进行插入操作时,不必移动其它结点,只需改动某个结点的指针,由空变为非空即可。搜索,插入,删除的复杂度等于树高,O(log(n)).

    二叉查找树的操作:

      /*二叉树的链式定义*/

    1 #define DataType int
    2 //二叉树的前序遍历
    3 typedef struct BiTNode    //二元查找树的节点
    4 {
    5     DataType m_Value;
    6     BiTNode *m_pLeft;
    7     BiTNode *m_pRight;
    8 }BiTNode;

      //创建二元查找树,相当于一个个的插入

     1 void addBSTreeNode(BiTNode *&pCurrent,DataType value)
     2 {
     3     if(NULL == pCurrent)    //如果是空的话就创建节点
     4     {
     5         BiTNode *pBSTree = new BiTNode();
     6         pBSTree->m_pLeft  = NULL;
     7         pBSTree->m_pRight = NULL;
     8         pBSTree->m_Value = value;
     9         pCurrent = pBSTree;
    10     }
    11     else
    12     {
    13         if(pCurrent->m_Value > value)
    14         {
    15             addBSTreeNode(pCurrent->m_pLeft,value);
    16         }
    17         else if(pCurrent->m_Value < value)
    18         {
    19             addBSTreeNode(pCurrent->m_pRight,value);
    20         }
    21         else
    22         {
    23             cout << "重复插入";
    24         }
    25     }
    26 }

      //二分查找树的搜索,时间复杂度O(logn)

     1 BiTNode * searchBSTreeNode(BiTNode *pCurrent,DataType value)
     2 {
     3     if(pCurrent == NULL || pCurrent->m_Value == value)
     4     {
     5         return pCurrent;
     6     }
     7     if(pCurrent->m_Value > value)
     8     {
     9         return searchBSTreeNode(pCurrent->m_pLeft,value);
    10     }
    11     else
    12     {
    13         return searchBSTreeNode(pCurrent->m_pRight,value);
    14     }
    15 }

      //返回二叉查找树中的最小值

    1 BiTNode * getMinValueFromBSTree(BiTNode *pCurrent)
    2 {
    3     while(pCurrent->m_pLeft)
    4         pCurrent = pCurrent->m_pLeft;
    5     return pCurrent;
    6 }

      //返回二叉查找树中的最大值

    1 BiTNode * getMaxValueFromBSTree(BiTNode *pCurrent)
    2 {
    3     while(pCurrent->m_pRight)
    4         pCurrent = pCurrent->m_pRight;
    5     return pCurrent;
    6 }

      //返回二叉查找树中的一个节点的后继结点

     1 BiTNode * getSuccessorNode(BiTNode *pCurrent,BiTNode *x)
     2 {
     3     if(!x||!pCurrent)
     4         return NULL;
     5     //如果x节点的右子树不为空,那么后继结点一定是右子树的最左结点
     6     if(x->m_pRight)
     7         return getMinValueFromBSTree(x->m_pRight);
     8     //如果是空节点
     9     while(pCurrent)
    10     {
    11         if(x->m_Value < pCurrent->m_Value)                //如果比正在检查的节点小,
    12             if(getMaxValueFromBSTree(pCurrent->m_pLeft)->m_Value == x->m_Value)    //根节点只有可能是他左子树的最大节点的后继结点
    13                 return pCurrent;
    14             else
    15                 pCurrent = pCurrent->m_pLeft;
    16         else
    17                 pCurrent = pCurrent->m_pRight;
    18     }
    19     return pCurrent;
    20 }

    //返回二叉查找树中的一个节点的前驱结点

     1 BiTNode * getPredecessorNode(BiTNode *pCurrent,BiTNode *x)
     2 {
     3     if(!x||!pCurrent)
     4         return NULL;
     5     //如果x节点的左子树不为空,那么后继结点一定是左子树的最右结点
     6     if(x->m_pLeft)
     7         return getMaxValueFromBSTree(x->m_pLeft);
     8     //如果是空节点
     9     while(pCurrent)
    10     {
    11         if(x->m_Value > pCurrent->m_Value)                                            //如果比正在检查的节点小,
    12             if(getMinValueFromBSTree(pCurrent->m_pRight)->m_Value == x->m_Value)    //根节点只有可能是他右子树的最小结点的前驱结点
    13                 return pCurrent;
    14             else
    15                 pCurrent = pCurrent->m_pRight;
    16         else
    17                 pCurrent = pCurrent->m_pLeft;
    18     }
    19     return pCurrent;
    20 }

      //返回一个结点的双亲结点

     1 BiTNode * getParentsNode(BiTNode *pCurrent,BiTNode * x)
     2 {
     3     if(!pCurrent || pCurrent == x ||!x)    //根为空或者就是根节点,则无父节点
     4         return NULL;
     5     while(pCurrent)
     6     {
     7         if(pCurrent->m_pLeft == x || pCurrent->m_pRight == x)
     8             return pCurrent;
     9         if(x->m_Value < pCurrent->m_Value)
    10             pCurrent = pCurrent->m_pLeft;
    11         else
    12             pCurrent = pCurrent->m_pRight;
    13     }
    14     return NULL;
    15 }

      //删除二叉查找树中一个值为指定值的结点---这个有点长,主要是有些重复的操作可以封装到函数中去,我没有!

      1 void deleteNodeFromBSTreeNode(BiTNode *&pCurrent,DataType value)
      2 {
      3     if(!pCurrent)
      4         return;
      5     BiTNode *fitNode = searchBSTreeNode(pCurrent,value);    //找到要删除的结点
      6     if(!fitNode)                                            //是NULL,直接返回。没找到要删除的结点
      7         return ;
      8     BiTNode *parents = getParentsNode(pCurrent,fitNode),*temp = NULL;    //得到要删除结点的父亲结点
      9     if(!fitNode->m_pLeft)    //如果左结点为空
     10     {
     11         if(parents)
     12         {
     13             if(fitNode == parents->m_pLeft)    //如果是父结点的左结点
     14             {
     15                 parents->m_pLeft = fitNode->m_pRight;
     16             }
     17             else
     18             {
     19                 parents->m_pRight = fitNode->m_pRight;
     20             }
     21         }
     22         else    //没有父结点,那要删除的就是根节点
     23         {
     24             pCurrent = fitNode->m_pRight;
     25         }
     26     }
     27     else if(!fitNode->m_pRight)        //如果右结点为空
     28     {
     29         if(parents)
     30         {
     31             if(fitNode == parents->m_pLeft)    //如果是父结点的左结点
     32             {
     33                 parents->m_pLeft = fitNode->m_pLeft;
     34             }
     35             else
     36             {
     37                 parents->m_pRight = fitNode->m_pLeft;
     38             }
     39         }
     40         else    //没有父结点,那要删除的就是根节点
     41         {
     42             pCurrent = fitNode->m_pLeft;
     43         }
     44     }
     45     else //左右孩子都不为空
     46     {
     47         //找到右子树中左边的的结点---即右子树最小值结点
     48         temp =  getMinValueFromBSTree(fitNode->m_pRight);
     49         if(fitNode->m_pRight != temp)    
     50         {
     51             BiTNode *parents1 = getParentsNode(pCurrent,temp);
     52             if(parents1)
     53             {
     54                 //肯定是在父结点的左结点上
     55                 parents1->m_pLeft = temp->m_pRight;
     56             }
     57             else
     58             {
     59                 //不可能没有父结点了
     60             }
     61             temp->m_pRight = fitNode->m_pRight;
     62             temp->m_pLeft  = fitNode->m_pLeft;
     63             if(parents)
     64             {
     65                 if(parents->m_pLeft == fitNode)
     66                 {
     67                     parents->m_pLeft =  temp;
     68                 }
     69                 else
     70                 {
     71                     parents->m_pRight = temp;
     72                 }
     73             }
     74             else
     75             {
     76                 pCurrent = temp;
     77             }
     78         }
     79         else
     80         {
     81             if(parents)
     82             {
     83                 if(parents->m_pLeft == fitNode)
     84                 {
     85                     parents->m_pLeft =  temp;
     86                     temp ->m_pLeft = fitNode->m_pLeft;
     87                 }
     88                 else
     89                 {
     90                     parents->m_pRight = temp;
     91                     temp ->m_pLeft = fitNode->m_pLeft;
     92                 }
     93             }
     94             else
     95             {
     96                 pCurrent = temp;
     97             }
     98         }
     99     }
    100 }

      //以下是对二叉查找树的操作实例

     1 int main()
     2 {
     3     BiTNode * root = NULL,*p;
     4     addBSTreeNode(root,15);
     5     addBSTreeNode(root,6);
     6     addBSTreeNode(root,18);
     7     addBSTreeNode(root,3);
     8     addBSTreeNode(root,7);
     9     addBSTreeNode(root,17);
    10     addBSTreeNode(root,20);
    11     addBSTreeNode(root,2);
    12     addBSTreeNode(root,4);
    13     addBSTreeNode(root,13);
    14     addBSTreeNode(root,9);
    15     p = searchBSTreeNode(root,18);
    16     if(p)    cout << &p << ":" << p->m_Value << endl;
    17     else    cout << "不存在!" << endl;
    18     cout << "最大值:" <<getMaxValueFromBSTree(root)->m_Value << endl;
    19     cout << "最小值:" <<getMinValueFromBSTree(root)->m_Value << endl;
    20     cout << "2后继结点值为:" << getSuccessorNode(root,searchBSTreeNode(root,2))->m_Value << endl;
    21     cout << "3后继结点值为:" << getSuccessorNode(root,searchBSTreeNode(root,3))->m_Value << endl;
    22     cout << "4后继结点值为:" << getSuccessorNode(root,searchBSTreeNode(root,4))->m_Value << endl;
    23     cout << "6后继结点值为:" << getSuccessorNode(root,searchBSTreeNode(root,6))->m_Value << endl;
    24     cout << "7后继结点值为:" << getSuccessorNode(root,searchBSTreeNode(root,7))->m_Value << endl;
    25     cout << "9后继结点值为:" << getSuccessorNode(root,searchBSTreeNode(root,9))->m_Value << endl;
    26     cout << "13后继结点值为:" << getSuccessorNode(root,searchBSTreeNode(root,13))->m_Value << endl;
    27     cout << "15后继结点值为:" << getSuccessorNode(root,searchBSTreeNode(root,15))->m_Value << endl;
    28     cout << "17后继结点值为:" << getSuccessorNode(root,searchBSTreeNode(root,17))->m_Value << endl;
    29     cout << "18后继结点值为:" << getSuccessorNode(root,searchBSTreeNode(root,18))->m_Value << endl;
    30 
    31 
    32     cout << "3前驱结点值为:" << getPredecessorNode(root,searchBSTreeNode(root,3))->m_Value << endl;
    33     cout << "4前驱结点值为:" << getPredecessorNode(root,searchBSTreeNode(root,4))->m_Value << endl;
    34     cout << "6前驱结点值为:" << getPredecessorNode(root,searchBSTreeNode(root,6))->m_Value << endl;
    35     cout << "7前驱结点值为:" << getPredecessorNode(root,searchBSTreeNode(root,7))->m_Value << endl;
    36     cout << "9前驱结点值为:" << getPredecessorNode(root,searchBSTreeNode(root,9))->m_Value << endl;
    37     cout << "13前驱结点值为:" << getPredecessorNode(root,searchBSTreeNode(root,13))->m_Value << endl;
    38     cout << "15前驱结点值为:" << getPredecessorNode(root,searchBSTreeNode(root,15))->m_Value << endl;
    39     cout << "17前驱结点值为:" << getPredecessorNode(root,searchBSTreeNode(root,17))->m_Value << endl;
    40     cout << "18前驱结点值为:" << getPredecessorNode(root,searchBSTreeNode(root,18))->m_Value << endl;
    41     cout << "20前驱结点值为:" << getPredecessorNode(root,searchBSTreeNode(root,20))->m_Value << endl;
    42 
    43     deleteNodeFromBSTreeNode(root,15);
    44     inOrderVisitUseRecur(root);
    45     cout << endl;
    46     return 0;
    47 }

      //以上代码全部本人手工敲上去的,如有错误请留言。如若转载,请注明出处!

  • 相关阅读:
    [POI2004] SZP (贪心+拓扑排序)
    【洛谷 P1525】 关押罪犯 (二分图+二分答案)
    【洛谷 P1073】 最优贸易 (Tarjan缩点+拓扑排序)
    【洛谷 P4320】 道路相遇 (圆方树,LCA)
    【CF1009F】 Dominant Indices (长链剖分+DP)
    【洛谷 P1707】 刷题比赛 (矩阵加速)
    【洛谷 P4568】 [JLOI2011]飞行路线 (分层最短路)
    【洛谷 P1129】 [ZJOI2007]矩阵游戏 (二分图匹配)
    【CF558E】 A Simple Task (权值线段树)
    【洛谷 P2303】 [SDOi2012]Longge的问题 (欧拉函数)
  • 原文地址:https://www.cnblogs.com/zhuwbox/p/3634883.html
Copyright © 2011-2022 走看看