• [BinaryTree] 二叉搜索树(二叉查找树、二叉排序树)


     二叉查找树(BinarySearch Tree,也叫二叉搜索树,或称二叉排序树BinarySort Tree)或者是一棵空树,或者是具有下列性质的二叉树:

    (1)若它的左子树不为空,则左子树上所有结点的值均小于它的根结点的值;

    (2)若它的右子树不为空,则右子树上所有结点的值均大于它的根结点的值;

    (3)它的左、右子树也分别为二叉查找树。

    下面是它的几个重要函数:

    插入结点:

    【思路1】递归

    终止条件(1,2):

    1.若插入到一个空树中,则新建结点为根结点,左右孩子置为空,返回true

    2.若等于根结点的值,返回false

    3.若当前值小于根结点的值,递归左子树,否则递归右子树

     1 template<class T>
     2 bool BinarySearchTree<T>::InsertNode(BinaryTreeNode<T> * &root, T newpointer)
     3 {
     4     if (root == NULL)
     5     {
     6         root = new BinaryTreeNode<T>;
     7         root->element = newpointer;
     8         root->LeftChild = root->RightChild = NULL;
     9         return true;
    10     }
    11     if (newpointer == root->element)
    12         return false;
    13     if (newpointer < root->element)
    14         return InsertNode(root->LeftChild, newpointer);
    15     else
    16         return InsertNode(root->RightChild, newpointer);
    17 }

    【思路2】非递归

    1.若二叉树为空,则首先单独生成根结点

    2.执行查找算法,找出被插结点的父亲结点

    3.判断被插结点是其父亲结点的左、右儿子,并将被插结点作为叶子结点插入

    注:新插入的结点总是叶子结点

     1 template<class T>
     2 bool BinarySearchTree<T>::InsertNode(BinaryTreeNode<T> * &root, T newpointer)
     3 {
     4     if (root == NULL)
     5     {
     6         root = new BinaryTreeNode<T>;
     7         root->element = newpointer;
     8         root->LeftChild = root->RightChild = NULL;
     9         return true;
    10     }
    11     BinaryTreeNode<T> *pointer = root;
    12     while(pointer != NULL)
    13     {
    14         if (newpointer == pointer->element)
    15             return false;
    16         else if (newpointer < pointer->element)
    17         {
    18             if(pointer->LeftChild == NULL)
    19             {
    20                 BinaryTreeNode<T>* l = new BinaryTreeNode<T>(newpointer);
    21                 l->LeftChild = l->RightChild = NULL;
    22                 pointer->LeftChild = l;
    23                 return true;
    24             }
    25             pointer = pointer->LeftChild;
    26         }
    27         else
    28         {
    29             if(pointer->RightChild == NULL)
    30             {
    31                 BinaryTreeNode<T>* r = new BinaryTreeNode<T>(newpointer);
    32                 r->LeftChild = r->RightChild = NULL;
    33                 pointer->RightChild = r;
    34                 return true;
    35             }
    36             pointer = pointer->RightChild;
    37         }
    38     }
    39 }

    删除结点:

    【思路】删除二叉搜索树中结点要根据删除的位置分情况讨论

    1.删除叶子结点

    操作:直接删除,更改它的父亲结点的相应指针场为空。

    2.删除结点只有左儿子或只有右儿子

    操作:将该结点的子树直接接到该结点位置

    3.删除结点有两个子结点

    (1)合并删除

    (2)通过复制进行删除

    选取替身(左子树中最大的结点或右子树中最小的结点)替换到删除结点的位置

      1 template<class T>
      2 void BinarySearchTree<T>::deleteBinarySearchTree(BinaryTreeNode<T>* root, T x)
      3 {
      4     bool find = false;
      5     int flag = 0;//标志要删除的结点是前驱结点pre的左孩子还是右孩子
      6     BinaryTreeNode<T> *pre = NULL;
      7     while (root && !find)
      8     {
      9         if (x == root->element)
     10         {
     11             find = true;
     12         }
     13         else if (x < root->element)
     14         {
     15             pre = root;
     16             root = root->LeftChild;
     17             flag = -1;
     18         }
     19         else
     20         {
     21             pre = root;
     22             root = root->RightChild;
     23             flag = 1;
     24         }
     25     }
     26     if (root == NULL)
     27     {
     28         cout << "未找到要删除元素" << endl;
     29         return;
     30     }
     31     //此时root为要删除结点
     32     
     33     //要删除结点是叶子结点
     34     if (root->isLeaf())
     35     {
     36         if (flag == 0)
     37         {
     38             delete root;
     39             root = NULL;
     40         }
     41         else if (flag == -1)
     42         {
     43             pre->LeftChild = NULL;
     44             delete root;
     45             root = NULL;
     46         }
     47         else
     48         {
     49             pre->RightChild = NULL;
     50             delete root;
     51             root = NULL;
     52         }
     53     }
     54     
     55     //要删除结点具有左右子结点
     56     else if (root->LeftChild && root->RightChild)
     57     {
     58         //复制删除,选取左子树中最大的结点替换
     59         BinaryTreeNode<T> *t = root;
     60         BinaryTreeNode<T> *s = root->LeftChild;
     61         while (s->RightChild)
     62         {
     63             t = s;
     64             s = s->RightChild;
     65         }
     66         root->element = s->element;
     67         
     68         //此时S只有左孩子,需要连接到它的前驱结点t上
     69         if (root == t)//while循环未执行
     70         {
     71             t->LeftChild = s->LeftChild;
     72         }
     73         else//while循环已执行
     74         {
     75             t->RightChild = s->LeftChild;
     76         }
     77         delete s;
     78         s = NULL;
     79     }
     80     
     81     else//要删除结点为单支子树根结点
     82     {
     83         if (flag == 0)//root为根结点
     84         {
     85             if (root->LeftChild)
     86             {
     87                 pre = root;
     88                 root = root->LeftChild;
     89                 delete pre;
     90                 pre = NULL;
     91             }
     92             else
     93             {
     94                 pre = root;
     95                 root = root->RightChild;
     96                 delete pre;
     97                 pre = NULL;
     98             }
     99         }
    100         else if (flag == -1)//root为pre的左子树
    101         {
    102             if (root->LeftChild)//要删除结点只存在左子树
    103             {
    104                 pre->LeftChild = root->LeftChild;
    105                 delete root;
    106                 root = NULL;
    107             }
    108             else//要删除结点只存在右子树
    109             {
    110                 pre->LeftChild = root->RightChild;
    111                 delete root;
    112                 root = NULL;
    113             }
    114         }
    115         else//root为pre的右子树
    116         {
    117             if (root->LeftChild)//要删除结点只存在左子树
    118             {
    119                 pre->RightChild = root->LeftChild;
    120                 delete root;
    121                 root = NULL;
    122             }
    123             else//要删除结点只存在右子树
    124             {
    125                 pre->RightChild = root->RightChild;
    126                 delete root;
    127                 root = NULL;
    128             }
    129         }
    130     }
    131 }

    查找结点:

    【思路】分割式查找法:

    1.若根结点的关键码等于查找的关键码,成功。

    2.否则,若小于根结点的关键码,查其左子树;大于根结点的关键码,查其右子树。

    二叉搜索树的高效率在于继续检索时只需查找两棵子树之一。

     1 template<class T>
     2 BinaryTreeNode<T>* BinarySearchTree<T>::Search(BinaryTreeNode<T>* root, T x)
     3 {
     4     BinaryTreeNode<T>* current = root;
     5     while((NULL != current) && (x != current->element))
     6     {
     7         if(x < current->element)
     8             current = Search(root->LeftChild,x);
     9         else
    10             current = Search(root->RightChild,x);
    11     }
    12     return current;
    13 }
  • 相关阅读:
    Maven部署构件至远程仓库
    Maven远程仓库的认证
    Maven远程仓库的配置
    Maven实战系列文章
    使用Maven私服的好处
    使用Mavne生成可以执行的jar文件
    Visual Studio for Mac 简介
    HTTP 2.0与HTTP 1.1区别
    使用Microsoft的IoC框架:Unity来对.NET应用进行解耦
    围绕央行系统升级所产生的常见问题
  • 原文地址:https://www.cnblogs.com/lca1826/p/6480876.html
Copyright © 2020-2023  润新知