【C++】-- 搜索二叉树(二)

简介: 【C++】-- 搜索二叉树

三、二叉搜索树操作(递归)

理解了非递归操作以后, 递归操作就很简单了:

1. #include<iostream>
2. using namespace std;
3. 
4. //树的节点可以支持多种类型
5. template<class K>
6. //树节点结构
7. struct BSTreeNode
8. {
9.  BSTreeNode<K>* _left;//左指针
10.   BSTreeNode<K>* _right;//右指针
11.   K _key;//值
12. 
13.   //构造函数
14.   BSTreeNode(const K& key)
15.     :_left(nullptr)
16.     , _right(nullptr)
17.     , _key(key)
18.   {}
19. };
20. 
21. template<class K>
22. class BStree//树结构
23. {
24.   typedef BSTreeNode<K> Node;
25. public:
26.   //递归查找
27.   Node* FindR(const K& key)
28.   {
29.     return _FindR(_root, key);
30.   }
31. 
32.   //递归插入
33.   bool InsertR(const K& key)
34.   {
35.     return _InsertR(_root, key);
36.   }
37. 
38.   //递归删除
39.   bool EraseR(const K& key)
40.   {
41.     return _EraseR(_root, key);
42.   }
43. private:
44.   Node* _root;
45. };

 由于_root是私有的,可以把递归子函数查找、插入、删除都定义成私有的

1.二叉搜索树的查找(递归)

递归查找:

1. private:
2. //查找
3.  Node* _FindR(Node* root, const K& key)
4.  {
5.    if (root == nullptr)//没找到
6.    {
7.      return nullptr;
8.    }
9. 
10.     if (key < root->_key)//到左子树去找
11.     {
12.       FindR(root->_left, key);
13.     }
14.     else if (key > root->_key)//到右子树去找
15.     {
16.       FindR(root->_right, key);
17.     }
18.     else//找到了
19.     {
20.       return root;
21.     }
22.   }

2.二叉搜索树的插入(递归)

递归插入:当找到的位置为空时才插入

1.  //插入 加了&,root是_root的别名,修改root就直接修改到上一层调用,不用找父亲
2.  bool _InsertR(Node*& root, const K& key)
3.  {
4.    if (root == nullptr)//找到位置了
5.    {
6.      root = new Node(key);
7.      return true;
8.    }
9.    if (key < root->_key)//到左子树去找位置
10.     {
11.       _InsertR(root->_left, key);
12.     }
13.     else if (key > root->_key)//到右子树去找位置
14.     {
15.       _InsertR(root->_right, key);
16.     }
17.     else//已存在,无需插入
18.     {
19.       return false;
20.     }
21.   }

3.二叉搜索树的删除(递归)

递归删除:和二叉树的删除(非递归)一样,找到后的删除也有两种方式,递归和非递归

找到后的非递归删除:

1. //插入 加了&,root是_root的别名,修改root就直接修改到上一层调用,不用找父亲 
2. bool _EraseR(Node*& root, const K& key)
3.  {
4.    if (root == nullptr)//没找到
5.    {
6.      return false;
7.    }
8.    if (key < root->_key)//到左子树去找
9.    {
10.       _EraseR(root->_left, key);
11.     }
12.     else if (key > root->_key)//到右子树去找
13.     {
14.       _EraseR(root->_right, key);
15.     }
16.     else
17.     {
18.       //找到了,root就是要删除的节点
19.       if (root->_left == nullptr)//root左为空
20.       {
21.         Node* del = root;
22.         root = root->_right;
23.         delete del;
24.       }
25.       else if (root->_right == nullptr)//root右为空
26.       {
27.         Node* del = root;
28.         root = root->_left;
29.         delete del;
30.       }
31.       else//root左右都不为空
32.       {
33.         //找到右子树最左节点替换
34.         Node* minParent = root;
35.         Node* minRight = root->_right;
36. 
37.         while (minRight->_left)
38.         {
39.           minParent = minRight;
40.           minRight = minRight->_left;
41.         }
42. 
43.         //保存替换节点的值
44.         cur->_key = minRight->_key;
45. 
46.         //链接
47.         if (minParent->_left == minRight)
48.         {
49.           minParent->_left = minRight->_right;
50.         }
51.         else
52.         {
53.           minParent->_right = minRight->_right;
54.         }
55. 
56.         //删除
57.         delete minRight;
58.       }
59.       return true;
60.     }
61.   }

找到后的递归删除:

1.      else//root左右都不为空
2.      {       
3. //找右子树最左节点
4.        Node* minRight = root->_right;
5.        while (minRight->_left)
6.        {
7.          minRight = minRight->_left;
8.        }
9. 
10.         //保存右子树最左节点的值
11.         K min = minRight->_key;
12. 
13.         //使用递归方法删除右子树最左节点
14.         _Erase(root->_right, min);
15.       }

四、二叉搜索树的默认成员函数

现在还剩下二叉搜索树的构造、拷贝构造、赋值运算符重载、析构函数。

1.构造

前面已经写过构造函数了, 即只需要把根初始化为空就行了:

1. public:
2.  //构造函数需要将根初始化为空就行了
3.  BSTree()
4.    :_root(nullptr)
5.  {}

2.拷贝构造

拷贝构造利用递归调用子函数不断拷贝节点:

1.  //拷贝构造
2.  BSTree(const BSTree<K>& t)
3.  {
4.    _root = t.copy(t._root);
5.  }

在子函数处:

1.  Node* _copy(Node* root)
2.  {
3.    if (root == nullptr)//如果根为空,直接返回
4.    {
5.      return;
6.    }
7. 
8.    Node* copyNode = new Node(root->_key);//创建根节点
9.    copyNode->_left = _copy(root->_left);//递归拷贝左子树节点
10.     copyNode->_right = _copy(root->_right);//递归拷贝右子树节点
11. 
12.     return copyNode;//返回根
13.   }

3.赋值运算符重载

借助拷贝构造用现代写法写:

1.  //赋值运算符重载(现代写法)
2.  BSTree& operator=(const BSTree<K>& t)
3.  {
4.    swap(_root,t._root);
5.    return *this;
6.  }

4.析构

递归调用子函数去析构

1.  //析构
2.  ~BSTree()
3.  {
4.    _Destroy(_root);
5.    _root = nullptr;
6.  }

在子函数处:

1.  _Destroy(root)
2.  {
3.    if (root == nullptr)
4.    {
5.      return;
6.    }
7.    _Destroy(root->_left);
8.    _Destroy(root->_right);
9.    delete root;
10.   }

相关文章
|
3月前
|
C++
二叉树进阶面试题(精华总结)【C++版本】
二叉树进阶面试题(精华总结)【C++版本】
|
3月前
|
存储 编译器 数据库
【C/C++ 数据结构 】线索二叉树全解析:从数学原理到C++实现
【C/C++ 数据结构 】线索二叉树全解析:从数学原理到C++实现
90 0
|
3月前
|
算法 C++ 开发者
【C/C++ 数据结构 】二叉树基本性质:对于任何一颗二叉树T,若其终端结点为n0 ,那么度数为2的结点数为n2。则n0=n2+1...
【C/C++ 数据结构 】二叉树基本性质:对于任何一颗二叉树T,若其终端结点为n0 ,那么度数为2的结点数为n2。则n0=n2+1...
44 0
|
1月前
|
存储 C++
【C++】二叉树进阶之二叉搜索树(下)
【C++】二叉树进阶之二叉搜索树(下)
18 4
|
1月前
|
Java 编译器 C++
【C++】二叉树进阶之二叉搜索树(上)
【C++】二叉树进阶之二叉搜索树(上)
19 3
|
1月前
|
算法 C++
【C++高阶】高效搜索的秘密:深入解析搜索二叉树
【C++高阶】高效搜索的秘密:深入解析搜索二叉树
27 2
|
3月前
|
存储 C++
【C++】二叉树进阶 -- 详解
【C++】二叉树进阶 -- 详解
|
3月前
|
存储 算法 数据管理
C++中利用随机策略优化二叉树操作效率的实现方法
C++中利用随机策略优化二叉树操作效率的实现方法
92 1
|
3月前
|
存储 C++
【C++练级之路】【Lv.14】二叉搜索树(进化的二叉树——BST)
【C++练级之路】【Lv.14】二叉搜索树(进化的二叉树——BST)
【C++练级之路】【Lv.14】二叉搜索树(进化的二叉树——BST)
|
3月前
|
存储 C++
二叉树的操作(C++实现)
二叉树的操作(C++实现)