[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.删除叶子结点

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

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

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

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

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

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

(1)合并删除

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

 

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

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

(2)通过复制进行删除

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

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

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

  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 }

 

    原文作者:Strawberry丶
    原文地址: https://www.cnblogs.com/lca1826/p/6480876.html
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞