文章目录
- 前言
- 一、K树
- 1.结点的定义
- 2.构造函数
- 3.拷贝构造函数
- 4.赋值运算符重载
- 5.析构函数
- 6.二叉搜索树的查找(find)
- 1.非递归
- 2.递归
- 7.二叉搜索树的插入(Insert)
- 1.非递归
- 2.递归
- 8.二叉搜素树的删除(Erase)
- 1.非递归
- 2.递归
- 9.中序遍历(InOrder)
- 二、KV树
- 二叉搜索树性能
前言
一、K树
K模型:K模型即只有key作为关键码,结构中只需要存储Key即可,关键码即为需要搜索到的值。
1.结点的定义
template<class K>
struct BSTreeNode
{BSTreeNode<K>* _left;BSTreeNode<K>* _right;K _key;BSTreeNode(const K&key):_left(nullptr),_right(nullptr),_key(key){}
};
2.构造函数
template<class K>
class BSTree {typedef BSTreeNode<K> Node;
public:BSTree() {_root = nullptr;}
3.拷贝构造函数
BSTree(const BSTree<K>& t) {_root = Copy(t._root);}
Node* Copy(Node* root) {if (root == nullptr) {return nullptr;}//递归进行拷贝Node* copyroot = new Node(root->_key);copyroot->_left = Copy(root->_left);copyroot->_right = Copy(root->_right);return copyroot;}
4.赋值运算符重载
BSTree<K>& operator=(BSTree<K> t) {
//先拷贝出t,让_root指向t的位置,进行交换
//后续调用析构函数直接析构t._rootswap(_root, t._root);return *this;}
5.析构函数
~BSTree() {Destroy(_root);}void Destroy(Node*& root) {if (root == nullptr) {return;}Destroy(root->_left);Destroy(root->_right);delete root;root = nullptr;}
6.二叉搜索树的查找(find)
二叉搜索树的查找
a、从根开始比较,查找,比根大则往右边走查找,比根小则往左边走查找。
b、最多查找高度次,走到到空,还没找到,这个值不存在。
1.非递归
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;}
2.递归
bool _FindR(Node*root,const K& key) {if (root == nullptr) {//说明已经找完没找到return false;}if (root->_key < key) {return _FindR(root->_right, key);}else if (root->_key > key) {return _FindR(root->_left, key);}else {return true;}}
7.二叉搜索树的插入(Insert)
. 二叉搜索树的插入
插入的具体过程如下:
a. 树为空,则直接新增节点,赋值给root指针
b. 树不空,按二叉搜索树性质查找插入位置,插入新节点
1.非递归
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 {//树中已经有key值不能再插入return false;}}cur = new Node(key);//cur为要插入结点if (parent->_key < key) {//判断cur插在父结点的左数还是右树parent->_right = cur;}else {parent->_left = cur;}return true;//插入成功}
2.递归
bool InsertR(const K&key) {return _InsertR(_root, key);}bool _InsertR(Node*& root, const K& key) {//这里为结点指针的引用,可以不需要父结点直接修改if (root == nullptr) {root = new Node(key);return true;}if (root->_key < key) {return _InsertR(root->_right, key);}else if (root->_key > key) {return _InsertR(root->_left, key);}else {return false;}}
8.二叉搜素树的删除(Erase)
首先查找元素是否在二叉搜索树中,如果不存在,则返回, 否则要删除的结点可能分下面四种情况:
a. 要删除的结点无孩子结点
b. 要删除的结点只有左孩子结点
c. 要删除的结点只有右孩子结点
d. 要删除的结点有左、右孩子结点
看起来有待删除节点有4中情况,实际情况a可以与情况b或者c合并起来,因此真正的删除过程
如下:
情况b:删除该结点且使被删除节点的双亲结点指向被删除节点的左孩子结点–直接删除
情况c:删除该结点且使被删除节点的双亲结点指向被删除结点的右孩子结点–直接删除
情况d:在它的右子树中寻找中序下的第一个结点(关键码最小),用它的值填补到被删除节点中,再来处理该结点的删除问题–替换法删除
1.非递归
bool Erase(const K& key) {Node* parent = nullptr;Node* cur = _root;while (cur) {//寻找要删除结点if (cur->_key < key) {parent = cur;cur = cur->_right;}else if (cur->_key > key) {parent = cur;cur = cur->_left;}else {//找到要删除结点//1. 要删除节点左边为空if (cur->_left == nullptr) {if (cur == _root) {//要删除结点为根节点,则改变根节点位置_root = _root->_right;}else {//判断要删除结点在父结点的左子树还是右子树if (parent->_right == cur) {//在父结点右子树则让其指向删除结点的右子树parent->_right = cur->_right;}else {parent->_left = cur->_right;}}}//2. 要删除节点右边为空else if (cur->_right == nullptr) {if (cur == _root) {//要删除结点为根节点,则改变根节点位置_root = _root->_left;}else {//判断要删除结点在父结点的左子树还是右子树if (parent->_right == cur) {parent->_right = cur->_left;}else {parent->_left = cur->_left;}}}else {//3.要删除结点左右子树都不为空Node* parent = cur;Node* leftMax = cur->_left;//寻找可替代结点,替代过好要满足二叉搜索树的性质//要删除结点左子树的最大值,或者右子树的最小值while (leftMax->_right) {//寻找左子树的最大值parent = leftMax;leftMax = leftMax->_right;}swap(leftMax->_key, cur->_key);//替代结点与被删除结点的值交换//这样leftMax就为要被删除的结点if (parent->_left == leftMax) {//判断leftMax在父结点的左子树还是右子树parent->_left = leftMax->_left;}else {parent->_right = leftMax->_left;}//改变指向cur = leftMax;}delete cur;return true;} }return false;}
2.递归
bool EraseR(const K&key) {return _EraseR(_root, key);}bool _EraseR(Node*& root, const K& key) {//这里为结点指针的引用,可以不需要父结点直接修改if (root == nullptr) {return false;}if (root->_key < key) {return _Erase(root->_right, key);}else if (root->_key > key) {return _Erase(root->_left, key);}//寻找要删除结点else {Node* del = root;//1. 要删除节点左边为空if (root->_left == nullptr) {root = root->_right;}//2. 要删除节点右边为空else if (root->_right == nullptr) {root = root->_left;}else {//3.要删除结点左右都不为空Node* leftMax = root->_left;while (leftMax->_right) {//寻找替代结点leftMax = leftMax->_right;}swap(root->_key, leftMax->_key);//交换值后,要删除的结点为leftMax,其在root的左子树return _Erase(root->_left, key);}delete del;return true;}}
9.中序遍历(InOrder)
void InOrder() {_InOrder(_root);cout << endl;}
void _InOrder(Node* root) {if (root == nullptr) {return;}_InOrder(root->_left);cout << root->_key << " ";_InOrder(root->_right);}
二、KV树
KV模型:每一个关键码key,都有与之对应的值Value,即<Key, Value>的键值对
namespace key_value {template<class K, class V>struct BSTreeNode{BSTreeNode<K, V>* _left;BSTreeNode<K, V>* _right;K _key;V _value;BSTreeNode(const K& key, const V& value):_left(nullptr), _right(nullptr), _key(key), _value(value){}};template<class K, class V>class BSTree {typedef BSTreeNode<K, V> Node;public:BSTree() {_root = nullptr;}BSTree(const BSTree<K, V>& t) {_root = Copy(t._root);}BSTree<K, V>& operator=(BSTree<K, V> t) {swap(_root, t._root);return *this;}~BSTree() {Destroy(_root);}bool InsertR(const K& key, const V& value) {return _InsertR(_root, key, value);}bool EraseR(const K& key) {return _Erase(_root, key);}Node* FindR(const K& key) {return _FindR(_root, key);}void InOrder() {_InOrder(_root);cout << endl;}private:Node* Copy(Node* root) {if (root == nullptr) {return nullptr;}Node* copyroot = new Node(root->_key);copyroot->_left = Copy(root->_left);copyroot->_right = Copy(root->_right);return copyroot;}void Destroy(Node*& root) {if (root == nullptr) {return;}Destroy(root->_left);Destroy(root->_right);delete root;root = nullptr;}Node* _FindR(Node* root, const K& key) {if (root == nullptr) {return nullptr;}if (root->_key < key) {return _FindR(root->_right, key);}else if (root->_key > key) {return _FindR(root->_left, key);}else {return root;}}bool _InsertR(Node*& root, const K& key, const V& value) {if (root == nullptr) {root = new Node(key, value);return true;}if (root->_key < key) {return _InsertR(root->_right, key, value);}else if (root->_key > key) {return _InsertR(root->_left, key, value);}else {return false;}}bool _Erase(Node*& root, const K& key) {if (root == nullptr) {return false;}if (root->_key < key) {return _Erase(root->_right, key);}else if (root->_key > key) {return _Erase(root->_left, key);}else {Node* del = root;if (root->_left == nullptr) {root = root->_right;}else if (root->_right == nullptr) {root = root->_left;}else {Node* leftMax = root->_left;while (leftMax->_right) {leftMax = leftMax->_right;}swap(root->_key, leftMax->_key);return _Erase(root->_left, key);}delete del;return true;}}void _InOrder(Node* root){if (root == NULL){return;}_InOrder(root->_left);cout << root->_key << ":" << root->_value << endl;_InOrder(root->_right);}private:Node* _root;};
}
二叉搜索树性能
最高找高度次O(N)