搜索二叉树的应用分为:
key模型:找key
key和value模型:通过key找到value的值
key的模型就是搜索二叉树。
而key和value模型就是通过值找值,举个栗子:当过安检时是不是刷身份证,那是如何得知乘客是否购买了票呢?
就是通过key和value模型,通过身份的ID寻找到购票的信息
只需要增加模板参数
并对余下个别功能进行修改如find,如insert
中英文互译
完整代码:
template<class k,class v>
struct BSTreenode
{
BSTreenode<k,v>* left;
BSTreenode<k,v>* right;
k _key;
v _value;
BSTreenode(k key,v value)
:left(nullptr)
, right(nullptr)
, _key(key)
,_value(value)
{
}
};
template<class k,class v>
class BSTree
{
typedef BSTreenode<k,v> node;//重写结点名字,方便
public:
bool erase(const k& key)
{
//先去找
//双指针法
node* cur = _root;
node* parent = nullptr;
while (cur)
{
if (cur->_key > key)
{
parent = cur;
cur = cur->left;
}
else if (cur->_key < key)
{
parent = cur;
cur = cur->right;
}
else
{
//找到了,分情况讨论
//只有一种的情况下:待删结点的子结点为右边
//如果cur两边都没有结点符合
if (cur->left == nullptr)
{
//确定parent的左连接到cur还是右连接到cur
if (parent->left == cur)
{
parent->left = cur->right;
}
else
{
parent->right = cur->right;
}
delete cur;
return true;
}//待删结点的子结点为左边
else if (cur->right == nullptr)
{
//确定parent的左连接到cur还是右连接到cur
if (parent->left == cur)
{
parent->left = cur->left;
}
else
{
parent->right = cur->left;
}
delete cur;
return true;
}
else
{
//只剩下两个结点的情况
node* rightsmall = cur->right;
node* rightsmallparent = cur;
while (rightsmall->left)//一直往左走就找到右子树的最小的
{//当这个条件结束rightsmall的左边已经没有值了所以就是最小的
rightsmallparent = rightsmall;
rightsmall = rightsmall->left;
}
cur->_key = rightsmall->_key;//赋值
//替代完成
//删除替代的原位置
if (rightsmall->left == nullptr)
{
if (rightsmallparent->left == rightsmall)
{
rightsmallparent->left = rightsmall->right;
}
else
{
rightsmallparent->right = rightsmall->right;
}
//因为rightsmall一直往左走
//所以是rightsmallparent的左孩子
}
else
{
if (rightsmallparent->left == rightsmall)
{
rightsmallparent->left = rightsmall->left;
}
else
{
rightsmallparent->right = rightsmall->left;
}
}
delete rightsmall;
return true;
}
return false;
}
}
}
bool insert(k key,v value)
{
//两种情况;
//树里没有数据和有数据俩种
if (_root == nullptr)
{
_root = new node(key,value);//开辟一个node对象然后调用初始化构造
return true;
}
else
{
//有数据,要找到正确位置
node* parent = nullptr;
node* cur = _root;
while (cur)
{
if (cur->_key > key)//证明待插入元素应该往左边
{
parent = cur;//cur是探测作用,parent是保存上一个指针地址
cur = cur->left;
}
else if (cur->_key < key)//证明待插入元素应该往右边
{
parent = cur;
cur = cur->right;
}
}
//当cur为nullptr就要找到待插入位置。
//但是,还要确定插在parent的左还是右
if (parent->_key > key)
{
parent->left = new node(key,value);
}
else
{
parent->right = new node(key,value);
}
}
}
void _InOrder(node* root)
{
if (root == nullptr)
{
return;
}
_InOrder(root->left);
cout << root->_key << " "<<root->_value<<endl;
_InOrder(root->right);
}
void InOrder()
{
_InOrder(_root);
cout << endl;
}
node* Find(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;
}
private:
node* _root = nullptr;//定义头指针
};
int main()
{
BSTree<string, string> _b;
_b.insert("sort", "排序");
_b.insert("tree", "树");
_b.insert("stack", "栈");
_b.insert("list", "链表");
_b.insert("queue", "队列");
string s;
while (cin >> s)
{
BSTreenode<string, string>* ret = _b.Find(s);
if (ret)
{
cout << ret->_value << endl;
}
else
{
cout << "查无此词" << endl;
}
}
}
统计数据
统计水果
统计水果完整代码(同用于上面的搜索二叉树的原理)
int main()
{
//统计数据
string strArr[] = { "西瓜","樱桃", "西瓜", "香蕉", "西瓜", "苹果", "西瓜","车厘子" };
BSTree<string, int> countTree;
for (auto a : strArr)
{
BSTreenode<string, int>* ret = countTree.Find(a);
if (ret == nullptr)
{
countTree.insert(a, 1);
}
else
{
ret->_value += 1;
}
}
countTree.InOrder();
}
注意:为什么使用搜索二叉树因为搜索”效率高“
如果插入的数据是有序的或着接近有序的?那搜索树的效率就没办法保证了