二叉搜索树又称二叉排序树,它或者是一棵空树,或者是具有以下性质的二叉树:
template<class K>
struct BSTreeNode
{
BSTreeNode<K>* _left;
BSTreeNode<K>* _right;
K _key;
BSTreeNode(const K& key)
:_left(nullptr)
,_right(nullptr)
,_key(key)
{}
};
template<class K>
class BSTree
{
typedef BSTreeNode<K> Node;
//.....成员函数
private:
Node* _root = nullptr;
};
循环实现
bool Insert(const K& key)
{
if (_root == nullptr)
{
_root = new Node(key);
return true;
}
Node* cur = _root;
Node* parent = cur;
while (cur)
{
parent = cur;
if (key > cur->_key)
{
cur = cur->_right;
}
else if (key < cur->_key)
{
cur = cur->_left;
}
else
{
return false;
}
}
Node* newnode = new Node(key);
if (key > parent->_key)
{
parent->_right = newnode;
}
else
{
parent->_left = newnode;
}
return true;
}
递归实现
通过root的引用可以解决:需要找到父节点才能插入的情况
引用不能改变指向,所以用循环的插入不能用引用
public:
bool InsertR(const K& key)
{
return _InsertR(_root,key);
}
protected:
bool _InsertR(Node*& root,const K& key)
{
if (root == nullptr)
{
root = new Node(key);
return true;
}
if (key < root->_key)
return _InsertR(root->_left, key);
else if (key > root->_key)
return _InsertR(root->_right, key);
else
return false;
}
首先查找元素是否在二叉搜索树中,如果不存在,则返回, 否则要删除的结点可能分下面四种情况:
a. 要删除的结点无孩子结点
b. 要删除的结点只有左孩子结点
c. 要删除的结点只有右孩子结点
d. 要删除的结点有左、右孩子结点
情况a可以与情况b或者c合并起来,因此真正的删除过程如下:
循环实现
bool Erase(const K& key)
{
//要删除的节点有三种情况
Node* cur = _root;
Node* parent = nullptr;
while (cur)
{
if (key > cur->_key)
{
parent = cur;
cur = cur->_right;
}
else if (key < cur->_key)
{
parent = cur;
cur = cur->_left;
}
else
{
//准备删除
if (cur->_left == nullptr)//只有右孩子
{
if (cur == _root)//如果碰到删最后几个节点的情况
{
_root = cur->_right;//更新新的根
//如果只有最后一个节点,_root变成nullptr,然后cur被delete
}
else
{
//判断一下parent用left还是right去链接cur的孩子
if (cur == parent->_left)
{
parent->_left = cur->_right;
}
else if (cur == parent->_right)
{
parent->_right = cur->_right;
}
else
{
cout << "quit" << endl;
return 0;
}
}
delete cur;
}
else if (cur->_right == nullptr)//只有左孩子
{
if (cur == _root)//如果碰到删最后几个节点的情况
{
_root = cur->_left;//更新新的根
//如果只有最后一个节点,_root变成nullptr,然后cur被delete
}
else
{
//判断一下parent用left还是right去链接cur的孩子
if (cur == parent->_left)
{
parent->_left = cur->_left;
}
else if (cur == parent->_right)
{
parent->_right = cur->_left;
}
else
{
cout << "quit" << endl;
return 0;
}
}
delete cur;
}
else//左右都有孩子,替换法
{
//通过中序找右树中的最小节点
Node* t = cur->_right;
Node* parent = cur;//记录t的父节点
while (t->_left)
{
parent = t;
t = t->_left;
}
swap(cur->_key, t->_key);
//交换后看t是parent的左还是右
if (t == parent->_left)
{
//t已经是最左,所以只可能有右孩子
parent->_left = t->_right;
}
else if (t == parent->_right)
{
parent->_right = t->_right;
}
else
{
cout << "quit" << endl;
return 0;
}
delete t;
}
return true;
}
}
return false;
}
递归实现
public:
bool EraseR(const K& key)
{
return _EraseR(_root,key);
}
protected:
bool _EraseR(Node*& root,const K& key)
{
if (root == nullptr)
{
return false;
}
if (key < root->_key)
{
return _EraseR(root->_left, key);
}
else if (key > root->_key)
{
return _EraseR(root->_right, key);
}
else
{
if (root->_left == nullptr)//只有右孩子
{
Node* t = root;
root = root->_right;
delete t;
return true;
}
else if (root->_right == nullptr)//只有左孩子
{
Node* t = root;
root = root->_left;
delete t;
return true;
}
else
{
//和右树的最小节点替换,也就是右树的最左
Node* t = root->_right;
while (t->_left)
{
t = t->_left;
}
swap(root->_key, t->_key);
//交换之后从头找是找不到的,但可以在右树找,然后再删除
return _EraseR(root->_right, key);
}
}
}
循环实现
bool Find(const K& key)
{
Node* cur = _root;
while (cur)
{
if (key > cur->_key)
{
cur = cur->_right;
}
else if (key < cur->_key)
{
cur = cur->_left;
}
else
{
//找到了
return true;
}
}
return false;
}
递归实现
public:
bool FindR(const K& key)
{
return _FindR(_root, key);
}
protected:
bool _FindR(Node* root,const K& key)
{
if (root == nullptr)
return false;
if (key < root->_key)
return _FindR(root->_left, key);
else if (key > root->_key)
return _FindR(root->_right, key);
else
return true;
}
#pragma once
#include
using namespace std;
template<class K>
struct BSTreeNode
{
BSTreeNode<K>* _left;
BSTreeNode<K>* _right;
K _key;
BSTreeNode(const K& key)
:_left(nullptr)
,_right(nullptr)
,_key(key)
{}
};
template<class K>
class BSTree
{
typedef BSTreeNode<K> Node;
public:
BSTree() = default;
BSTree(const BSTree<K>& t)
{
_root = copy(t._root);
}
BSTree<K> operator=(BSTree<K> t)
{
swap(_root,t._root);
return *this;
}
bool Insert(const K& key)
{
if (_root == nullptr)
{
_root = new Node(key);
return true;
}
Node* cur = _root;
Node* parent = cur;
while (cur)
{
parent = cur;
if (key > cur->_key)
{
cur = cur->_right;
}
else if (key < cur->_key)
{
cur = cur->_left;
}
else
{
return false;
}
}
Node* newnode = new Node(key);
if (key > parent->_key)
{
parent->_right = newnode;
}
else
{
parent->_left = newnode;
}
return true;
}
bool Erase(const K& key)
{
//要删除的节点有三种情况
Node* cur = _root;
Node* parent = nullptr;
while (cur)
{
if (key > cur->_key)
{
parent = cur;
cur = cur->_right;
}
else if (key < cur->_key)
{
parent = cur;
cur = cur->_left;
}
else
{
//准备删除
if (cur->_left == nullptr)//只有右孩子
{
if (cur == _root)//如果碰到删最后几个节点的情况
{
_root = cur->_right;//更新新的根
//如果只有最后一个节点,_root变成nullptr,然后cur被delete
}
else
{
//判断一下parent用left还是right去链接cur的孩子
if (cur == parent->_left)
{
parent->_left = cur->_right;
}
else if (cur == parent->_right)
{
parent->_right = cur->_right;
}
else
{
cout << "quit" << endl;
return 0;
}
}
delete cur;
}
else if (cur->_right == nullptr)//只有左孩子
{
if (cur == _root)//如果碰到删最后几个节点的情况
{
_root = cur->_left;//更新新的根
//如果只有最后一个节点,_root变成nullptr,然后cur被delete
}
else
{
//判断一下parent用left还是right去链接cur的孩子
if (cur == parent->_left)
{
parent->_left = cur->_left;
}
else if (cur == parent->_right)
{
parent->_right = cur->_left;
}
else
{
cout << "quit" << endl;
return 0;
}
}
delete cur;
}
else//左右都有孩子,替换法
{
//通过中序找右树中的最小节点
Node* t = cur->_right;
Node* parent = cur;//记录t的父节点
while (t->_left)
{
parent = t;
t = t->_left;
}
swap(cur->_key, t->_key);
//交换后看t是parent的左还是右
if (t == parent->_left)
{
//t已经是最左,所以只可能有右孩子
parent->_left = t->_right;
}
else if (t == parent->_right)
{
parent->_right = t->_right;
}
else
{
cout << "quit" << endl;
return 0;
}
delete t;
}
return true;
}
}
return false;
}
bool Find(const K& key)
{
Node* cur = _root;
while (cur)
{
if (key > cur->_key)
{
cur = cur->_right;
}
else if (key < cur->_key)
{
cur = cur->_left;
}
else
{
//找到了
return true;
}
}
return false;
}
bool InsertR(const K& key)
{
return _InsertR(_root,key);
}
bool EraseR(const K& key)
{
return _EraseR(_root,key);
}
bool FindR(const K& key)
{
return _FindR(_root, key);
}
void InOrder()
{
_InOrder(_root);
cout << endl;
}
~BSTree()
{
Destroy(_root);
}
protected:
void Destroy(Node* &root)
{
if (root == nullptr)
return;
Destroy(root->_left);
Destroy(root->_right);
delete root;
root = nullptr;
}
Node* copy(Node* root)
{
if (root == nullptr)
return nullptr;
Node* newnode = new Node(root->_key);
newnode->_left = copy(root->_left);
newnode->_right = copy(root->_right);
return newnode;
}
bool _FindR(Node* root,const K& key)
{
if (root == nullptr)
return false;
if (key < root->_key)
return _FindR(root->_left, key);
else if (key > root->_key)
return _FindR(root->_right, key);
else
return true;
}
bool _InsertR(Node*& root,const K& key)
{
if (root == nullptr)
{
root = new Node(key);
return true;
}
if (key < root->_key)
return _InsertR(root->_left, key);
else if (key > root->_key)
return _InsertR(root->_right, key);
else
return false;
}
bool _EraseR(Node*& root,const K& key)
{
if (root == nullptr)
{
return false;
}
if (key < root->_key)
{
return _EraseR(root->_left, key);
}
else if (key > root->_key)
{
return _EraseR(root->_right, key);
}
else
{
if (root->_left == nullptr)//只有右孩子
{
Node* t = root;
root = root->_right;
delete t;
return true;
}
else if (root->_right == nullptr)//只有左孩子
{
Node* t = root;
root = root->_left;
delete t;
return true;
}
else
{
//和右树的最小节点替换,也就是右树的最左
Node* t = root->_right;
while (t->_left)
{
t = t->_left;
}
swap(root->_key, t->_key);
//交换之后从头找是找不到的,但可以在右树找,然后再删除
return _EraseR(root->_right, key);
}
}
}
void _InOrder(Node* root)
{
if (root == nullptr)
return;
_InOrder(root->_left);
cout << root->_key << " ";
_InOrder(root->_right);
}
private:
Node* _root = nullptr;
};
int main()
{
BSTree<int> at;
int a[] = { 2,6,3,1,9,5,7,8,4 };
for (auto e : a)
{
//cout << e << endl;
at.InsertR(e);
}
at.InOrder();
BSTree<int> bt;
bt = at;
bt.InOrder();
cout << bt.FindR(5) << endl;
cout << bt.FindR(22) << endl;
for (auto e : a)
{
//cout << e << endl;
bt.EraseR(e);
bt.InOrder();
}
bt.InOrder();
return 0;
}
K模型:K模型即只有key作为关键码,结构中只需要存储Key即可,关键码即为需要搜索到的值。
比如:给一个单词word,判断该单词是否拼写正确,具体方式下:
KV模型:每一个关键码key,都有与之对应的值Value,即
kv模型只需要在k模型的基础上做些许改动:
namespace kv
{
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:
bool Insert(const K& key, const V& value)
{
if (_root == nullptr)
{
_root = new Node(key, value);
return true;
}
Node* parent = nullptr;
Node* cur = _root;
while (cur)
{
parent = cur;
if (cur->_key < key)
{
cur = cur->_right;
}
else if (cur->_key > key)
{
cur = cur->_left;
}
else
{
return false;
}
}
cur = new Node(key, value);
if (parent->_key < key)
{
parent->_right = cur;
}
else
{
parent->_left = cur;
}
return true;
}
Node* 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 cur;
}
}
return nullptr;
}
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
{
// 准备删除 20:15继续
if (cur->_left == nullptr)
{//左为空
if (cur == _root)
{
_root = cur->_right;
}
else
{
if (cur == parent->_left)
{
parent->_left = cur->_right;
}
else
{
parent->_right = cur->_right;
}
}
}
else if (cur->_right == nullptr)
{//右为空
if (cur == _root)
{
_root = cur->_left;
}
else
{
if (cur == parent->_left)
{
parent->_left = cur->_left;
}
else
{
parent->_right = cur->_left;
}
}
}
else
{//左右都不为空
// 右树的最小节点(最左节点)
Node* parent = cur;
Node* subLeft = cur->_right;
while (subLeft->_left)
{
parent = subLeft;
subLeft = subLeft->_left;
}
swap(cur->_key, subLeft->_key);
if (subLeft == parent->_left)
parent->_left = subLeft->_right;
else
parent->_right = subLeft->_right;
}
return true;
}
}
return false;
}
void InOrder()
{
_InOrder(_root);
cout << endl;
}
private:
void _InOrder(Node* root)
{
if (root == nullptr)
return;
_InOrder(root->_left);
cout << root->_key << ":" << root->_value << endl;
_InOrder(root->_right);
}
private:
Node* _root = nullptr;
};
}
统计次数:
int main()
{
string arr[] = { "苹果", "苹果","香蕉", "菠萝", "西瓜", "椰子", "西瓜", "香蕉", "西瓜", "苹果", "菠萝"};
kv::BSTree<string, int> countTree;
for (auto& e : arr)
{
kv::BSTreeNode<string, int>* ret = countTree.Find(e);
if (ret == nullptr)
{
countTree.Insert(e, 1);
}
else
{
ret->_value++;
}
}
countTree.InOrder();
return 0;
}