C++(进阶) 第3章 二叉搜索树
前言
之前在数据布局篇简朴的介绍了二叉搜索树,本篇博客会具体的介绍
一、什么是二叉搜索树?
⼆叉搜索树的概念
⼆叉搜索树⼜称⼆叉排序树,它或者是⼀棵空树,或者是具有以下性质的⼆叉树:
• 若它的左⼦树不为空,则左⼦树上全部结点的值都⼩于等于根结点的值
• 若它的右⼦树不为空,则右⼦树上全部结点的值都⼤于等于根结点的值
• 它的左右⼦树也分别为⼆叉搜索树
下面就是一颗比力经典的二叉搜索树
搜索二叉树也叫排序二叉树,由于它走中序遍历的时候刚好就是有序的
二、搜索二叉树的实现
0.搜索二叉树的时间复杂度
搜索二叉树的做好环境下时间复杂度就是log N,但是会出现极端环境
以是时间复杂度就是N
但是后面会有AVL树,红黑树,可以优化差不多 log N
1.根本框架
- #include<bits/stdc++.h>
- using namespace std;
- template<class K>
- struct BSTreeNode
- {
- K _key;
- BSTreeNode<K>* _left;
- BSTreeNode<K>* _right;
- BSTreeNode(const K& key)
- :_key(key)
- ,_left(nullptr)
- ,_right(nullptr)
- {
- }
- };
- template<class K>
- class BSTree
- {
- typedef BSTreeNode<K> Node;
- public:
- private:
- Node* _root = nullptr;
- };
复制代码 2.Find
普通的二叉树其实没有什么意义,如果只是普通的二叉树它存东西的效率其实还不如链表,以是在原来的二叉树基础上添加了一些规则,左孩子比根小,右孩子比根大
如果就用下面的例子,现在我要在这颗树里面搜索看看有没有16这个数字
如果我们查找的值比根大那么就可以直接往右走,比根小只必要往左走就可以了那么最多只必要找这棵树的高度次就可以了
如果找到null了那么就阐明找不到
- bool Find(const K& key)
- {
- Node* cur = _root;
- while (cur)
- {
- if (cur->_key < key)
- {
- cur = cur->_right;
- }
- else if(cur->_key > key)
- {
- cur = cur->_left;
- }
- else
- {
- return true;
- }
- }
- return false;
- }
复制代码 3.Insert
注意:这里有一个规定,树里面的数据是不允许重复的,也,如果树里面已经有了10,那么这里就不允许再次插入,以是这里insert返回值用bool
- bool Insert(const K& key)
- {
- if (_root == nullptr)
- {
- _root = new Node(key);
- return true;
- }
- Node* cur = _root;
- Node* parent = nullptr;
- while (cur)
- {
- if (cur->_key < key)
- {
- parent = cur;
- cur = cur->_right;
-
- }
- else if (cur->_key > key)
- {
- parent = cur;
- cur = cur->_left;
-
- }
- else
- {
- return false;
- }
- }
- cur = new Node(key);
- if (parent->_key < cur->_key)
- {
- parent->_right = cur;
- }
- else
- {
- parent->_left= cur;
- }
- return true;
- }
复制代码 4.InOder
这里我用的是子函数的情势由于如果不这样的话,外面调用就要传入参数(_root)但是这里我_root是保护调用不了,
- void InOder()
- {
- _InOder(_root);
- }
- private:
- void _InOder(Node* root)
- {
- if (root == nullptr)
- {
- return;
- }
- _InOder(root->_left);
- cout << root->_key << ' ';
- _InOder(root->_right);
- }
复制代码 写完中序遍历就可以看下程序有没有写错了
这里可以看到输出的是有序的,就阐明这里是没有写错的
到这里的完备代码就长这样
- #pragma once#include<bits/stdc++.h>using namespace std;template<class K>struct BSTreeNode{ K _key; BSTreeNode<K>* _left; BSTreeNode<K>* _right; BSTreeNode(const K& key) :_key(key) ,_left(nullptr) ,_right(nullptr) { }};template<class K>class BSTree{ typedef BSTreeNode<K> Node;public: bool Find(const K& key) { Node* cur = _root; while (cur) { if (cur->_key < key) { cur = cur->_right; } else if(cur->_key > key) { cur = cur->_left; } else { return true; } } return false; } bool Insert(const K& key) { if (_root == nullptr) { _root = new Node(key); return true; } Node* cur = _root; Node* parent = nullptr; while (cur) { if (cur->_key < key) { parent = cur; cur = cur->_right; } else if (cur->_key > key) { parent = cur; cur = cur->_left; } else { return false; } } cur = new Node(key); if (parent->_key < cur->_key) { parent->_right = cur; } else { parent->_left= cur; } return true; } void InOder(Node* root) { if (root == nullptr) { return; } InOder(root->_left); cout << root->_key << ' '; InOder(root->_right); } void InOder()
- {
- _InOder(_root);
- }
- private:
- void _InOder(Node* root)
- {
- if (root == nullptr)
- {
- return;
- }
- _InOder(root->_left);
- cout << root->_key << ' ';
- _InOder(root->_right);
- }
- private: Node* _root = nullptr;};
复制代码- #define _CRT_SECURE_NO_WARNINGS
- #include"bstree.h"
- int main()
- {
- int arr[] = { 8,3,1,10,6,4,7,14,13 };
- BSTree<int> t;
- for (auto e : arr)
- {
- t.Insert(e);
- }
- t.InOder();
- return 0;
- }
复制代码 5.Erase
这里删除的话就比力复杂了,必要先找到要删的谁人节点,然后删除,但是删除的谁人节点大概会还有孩子并且删除了以后搜索二叉树不能乱,大致可以分成以下三种环境
如果这里我要删除3,那么我必要找到一个人替换3的位置,这个时候左子树最右边的节点,或者右子树最左边的节点都可以,以是上面的1,2种环境可以归类成一种环境,由于最左边或者最左边的一定是只有一个孩子或者没有孩子的环境
如果上面我要删掉3,那么我去找右子树的最左边的值也就是4,那么3替换成4,然后下面的4就可以直接删掉了
- bool Erase(const K& key)
- {
- Node* cur = _root;
- Node* parent = nullptr;
- while (cur)
- {
- if (cur->_key < key)
- {
- parent = cur;
- cur = cur->_right;
- }
- else if (cur->_key > key)
- {
- parent = cur;
- cur = cur->_left;
- }
- else
- {
- if (cur->_left == nullptr)
- {
- if (parent == nullptr)
- {
- _root = cur->_right;
- }
- else
- {
- if (parent->_left == cur)
- {
- parent->_left = cur->_right;
- }
- else
- {
- parent->_right = cur->_right;
- }
- }
-
- delete cur;
- return true;
- }
- else if(cur->_right == nullptr)
- {
- if (parent == nullptr)
- {
- _root = cur->_left;
- }
- else
- {
- if (parent->_left == cur)
- {
- parent->_left = cur->_left;
- }
- else
- {
- parent->_right = cur->_left;
- }
- }
-
- delete cur;
- return true;
- }
- else
- {
- Node* RightMin = cur->_right;
- Node* RightMinP = cur;
- while (RightMin ->_left)
- {
- RightMinP = RightMin;
- RightMin = RightMin->_left;
- }
- cur->_key = RightMin->_key;
- if (RightMinP->_left == RightMin )
- {
- RightMinP->_left = RightMin->_right;
- }
- else
- {
- RightMinP->_right = RightMin->_right;
- }
-
- delete RightMin;
- return true;
- }
- }
- }
- return false;
- }
复制代码
三 、完备代码
- #define _CRT_SECURE_NO_WARNINGS
- #include"BStree.h"
- using namespace std;
- int main()
- {
- int arr[] = { 8,3,1,10,6,4,7,14,13 };
- BSTree<int> t;
- for (auto e : arr)
- {
- t.Insert(e);
- }
- t.Insert(16);
- t.Insert(4);
- t.InOrder();
- for (auto e : arr)
- {
- t.Erase(e);
- t.InOrder();
- }
- return 0;
- }
复制代码 总结
删除有点复杂照旧要花时间去明白
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |