【C++】二叉搜索树KV模型

不了解二叉搜索树可以阅读我上一篇博客:二叉搜索树
KV模型:每一个关键码key,都有与之对应的值Value,即<Key, Value>的键值对。

该种方式在现实生活中非常常见:
比如英汉词典就是英文与中文的对应关系,通过英文可以快速找到与其对应的中文,英文单词与其对应的中文<word, chinese>就构成一种键值对;
再比如统计单词次数,统计成功后,给定单词就可快速找到其出现的次数,单词与其出现次数就是<word, count>就构成一种键值对。
比如:实现一个简单的英汉词典dict,可以通过英文找到与其对应的中文

具体实现方式如下:
<单词,中文含义>为键值对构造二叉搜索树
注意:二叉搜索树需要比较,键值对比较时只比较Key;查询英文单词时,只需给出英文单词,就可快速找到与其对应的key

查看各个功能模块的思路,请移步:二叉搜索树
代码实现:

#define _CRT_SECURE_NO_WARNINGS 1
#define _CRT_SECURE_NO_WARNINGS 1

#include <iostream>

using namespace std;
template <class K,class V>
struct BNode {
	//T data_;
	K  _key;		//类似于索引
	V _value;		//类似于data_

	typedef BNode<K,V> Node;
	Node* left;
	Node* right;

	BNode(const K&key,const V&value) :_key(key),_value(value),left(nullptr), right(nullptr)
	{}
};

template<class K,class V>
class BTree {
public:
	typedef BNode<K,V> Node;
	BTree() :root_(nullptr)
	{}

	//不插入重复的值
	bool insert(const K&key,const V&value)
	{
		if (root_ == nullptr)
		{
			root_ = new Node(key,value);
			return true;
		}

		//搜索
		Node* cur = root_;
		Node* parent = nullptr;
		while (cur)
		{
			parent = cur;
			if (cur->_key == key)
				return false;
			else if (cur->_key > key)
				cur = cur->left;
			else
				cur = cur->right;
		}
		//插入
		cur = new Node(key,value);
		if (parent->_key > key)
			parent->left = cur;
		else
			parent->right = cur;

		return true;
	}

	Node* find(const K& key)
	{
		Node* cur = root_;
		while (cur)
		{
			if (cur->_key == key)
				return cur;
			else if (cur->_key > key)
				cur = cur->left;
			else
				cur = cur->right;
		}
		return cur;
	}



	void inorder()
	{
		_inorder(root_);
	}

	//搜索树中序遍历:有序
	void _inorder(Node* root_)
	{
		if (root_)
		{
			_inorder(root_->left);
			cout << root_->_key << "-->"<<root_->_value<<" ";
			_inorder(root_->right);
		}
	}

	//拷贝二叉搜索树的数据和结构
	Node* copy(Node* root)
	{
		if (root == nullptr)
			return nullptr;
		
		//拷贝根
		Node* newnode = new Node(root->_key,root->_value);
		//拷贝左子树
		newnode->left = copy(root->left);
		//拷贝右子树
		newnode->right = copy(root->right);

		return newnode;
	}

	//删除
	bool erase(const K& key)
	{
		//查找
		Node* cur = root_;
		Node* parent = nullptr;
		while (cur)
		{
			if (cur->_key == key)
				break;
			parent = cur;
			if (cur->_key > key)
				cur = cur->left;
			else
				cur = cur->right;
		}
		//判断需要删除的结点是否找到
		if (cur == nullptr)
			return false;

		//删除
		//1.删除的为叶子节点
		if (cur->left == nullptr&&cur->right == nullptr)
		{
			//判断是否为根结点
			if (cur == root_)
			{
				root_ = nullptr;
			}
			else
			{
				//判断需要删除的结点在父节点哪一边
				if (parent->left == cur)
					parent->left = nullptr;
				else
					parent->right = nullptr;
			}
			//删除结点
			delete cur;
		}

		//2.删除的为非叶子结点:
		//2.1左子树为空
		else if (cur->left == nullptr)
		{
			//判断根结点是否为要删除的结点
			if (cur == root_)
			{
				root_ = cur->right;
			}
			else
			{
				//更新链接
				if (parent->left == cur)
					parent->left = cur->right;
				else
					parent->right = cur->right;
			}
			//删除结点
			delete cur;
		}
		//2.2右子树为空
		else if (cur->right == nullptr)
		{
			//判断根结点是否为要删除的结点
			if (cur == root_)
			{
				//更新根结点
				root_ = cur->left;
			}
			else
			{
				//更新链接
				if (parent->left == cur)
					parent->left = cur->left;
				else
					parent->right = cur->left;
			}
			//删除结点
			delete cur;
		}
		//2.3要删除的结点有左右孩子
		else
		{
			//1.假设找左子树的最右结点
			Node* leftRightMost = cur->left;
			parent = cur;
			while (leftRightMost->right)
			{
				parent = leftRightMost;
				leftRightMost = leftRightMost->right;
			}
			//2.交换
			swap(cur->_key, leftRightMost->_key);
			swap(cur->_value, leftRightMost->_value);

			//3.删除最右结点
			if (parent->left == leftRightMost)
				parent->left = leftRightMost->left;
			else
				parent->right = leftRightMost->left;

			delete leftRightMost;
		}

		return true;
	}

	//在成员初始化列表阶段调用copy()函数进行拷贝构造
	BTree(const BTree<K,V>& btree) :root_(copy(btree.root_))
	{}

	void destroy(Node* root)
	{
		if (root)
		{
			destroy(root->left);
			destroy(root->right);
			cout << "destroy:" << root->_key <<"-->"<<root->_value<<endl;
			delete root;
		}
	}

	~BTree()
	{
		if (root_)
		{
			destroy(root_);
			root_ = nullptr;
		}
	}

private:
	Node* root_;
};


void test()
{
	BTree<int, int>b;
	b.insert(5,50);
	b.insert(3, 50);
	b.insert(7, 50);
	b.insert(1, 50);
	b.insert(4, 50);
	b.insert(6, 50);
	b.insert(8, 50);
	cout << endl;
	b.inorder();
}
int main()
{
	test();
	return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值