数据结构:二叉搜索树(非递归实现)

本文详细介绍了二叉搜索树的基本概念、查找、插入和删除操作,以及非递归代码实现,探讨了K模型和KV模型的应用实例。
摘要由CSDN通过智能技术生成

目录

1、二叉搜索树

2、二叉搜索树的相关操作。

1、查找

2、插入

3、删除

3、代码实现(非递归)


1、二叉搜索树

二叉搜索树(Binary Search Tree,简称BST)是一种特殊的二叉树,其中每个节点的值大于其左子树中所有节点的值,小于其右子树中所有节点的值。这种特性使得二叉搜索树具有快速的查找、插入和删除操作。

二叉搜索树的性质包括:

  1. 左子树中所有节点的值小于根节点的值;
  2. 右子树中所有节点的值大于根节点的值;
  3. 左右子树也分别为二叉搜索树。

如下图所示:

                                           

2、二叉搜索树的相关操作。

1、查找

a、从根开始比较,查找,比根大则往右边走查找,比根小则往左边走查找。
b、最多查找高度次,走到到空,还没找到,这个值不存在。

2、插入

a. 树为空,则直接新增节点,赋值给root指针
b. 树不空,按二叉搜索树性质查找插入位置,插入新节点

3、删除

删除操作也是最值得思考的操作,因为有四种情况

a. 要删除的结点无孩子结点
这是最简单的情况,直接删除节点就好,并且将该节点的父节点对应的指针置为nullptr
b. 要删除的结点只有左孩子结点
如果为根节点,那么直接让该节点的左孩子变为根节点即可。
如果不为根节点,那么需要判断该节点是prev(该节点的父节点)的左孩子还是右孩子,让对应的指针指向该节点的左孩子即可。
c. 要删除的结点只有右孩子结点
如果为根节点,同上操作,只是变为对该节点右孩子的操作
不为根节点,判断该节点是prev(该节点的父节点)的左孩子还是右孩子,让对应的指针指向该节点的右孩子即可。
d. 要删除的结点有左、右孩子结点
如果该节点有左孩子和右孩子,那么如何操作才能在不破坏二叉搜索树结构的情况下完成删除呢?
我们需要找到该节点的 最小右孩子来替换该节点,这样就可以解决问题。
最小右孩子:
最小右孩子分为两种情况:
1.当前节点的右孩子节点的最小左孩子
2.若是当前节点的右孩子节点没有最小左孩子,那么当前节点的右孩子节点就是最小右孩子。
下面是一段代码 实现,cur就是 当前要删除的节点,我们将它设为初始的最小右孩子的父节点,然后while循环查找最小左孩子,最后判断最小右孩子是该父节点的左右指针,将对应指针指向RightMin->_right;
						Node* RightMinParent = cur;
						Node* RightMin = cur->_right;
						while (RightMin->_left)
						{
							RightMinParent = RightMin;
							RightMin = RightMin->_left;
						}
						cur->_key = RightMin->_key;
						if (RightMin == RightMinParent->_left)
						{
							RightMinParent->_left = RightMin->_right;
						}
						else
						{
							RightMinParent->_right = RightMin->_right;
						}

						delete RightMin;
						return true;

3、代码实现(非递归)

二叉搜索树的实现:

1.  K 模型: K 模型即只有 key 作为关键码,结构中只需要存储 Key 即可,关键码即为需要搜索到
的值
比如: 给一个单词 word ,判断该单词是否拼写正确 ,具体方式如下:
以词库中所有单词集合中的每个单词作为 key ,构建一棵二叉搜索树
在二叉搜索树中检索该单词是否存在,存在则拼写正确,不存在则拼写错误。
2. KV 模型:每一个关键码 key ,都有与之对应的值 Value ,即 <Key, Value> 的键值对 。该种方
式在现实生活中非常常见:
比如 英汉词典就是英文与中文的对应关系 ,通过英文可以快速找到与其对应的中文,英文单词与其对应的中文<word, chinese> 就构成一种键值对;
再比如 统计单词次数 ,统计成功后,给定单词就可快速找到其出现的次数, 单词与其出
现次数就是 <word, count> 就构成一种键值对
#pragma once
namespace key_value
{
	template<class K, class V>
	struct BSTreeNode
	{
		typedef BSTreeNode<K, V> Node;
		Node* _left;
		Node* _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* prev = nullptr;
			Node* cur = _root;
			while (cur)
			{
				if (cur->_key > key)
				{
					prev = cur;
					cur = cur->_left;
				}
				else if (cur->_key < key)
				{
					prev = cur;
					cur = cur->_right;
				}
				else
				{
					return false;
				}
			}

			Node* newnode = new Node(key,value);
			if (prev->_key > key)
			{
				prev->_left = newnode;
			}
			else if (prev->_key < key)
			{
				prev->_right = newnode;
			}
			
			return true;

		}

		Node* Find(const K& key)
		{
			Node* cur = _root;
			while (cur)
			{
				if (cur->_key > key)
				{
					cur = cur->_left;
				}
				else if (cur->_key < key)
				{
					cur = cur->_right;
				}
				else
				{
					return cur;
				}
			}
		}

		bool Erase(const K& key)
		{
			Node* prev = nullptr;
			Node* cur = _root;
			while (cur)
			{
				if (cur->_key > key)
				{
					prev = cur;
					cur = cur->_left;
				}
				else if(cur->_key<key)
				{
					prev = cur;
					cur = cur->_right;
				}
				else
				{
					if (cur->_left == nullptr)
					{
						if (cur == _root)
						{
							cur = cur->_right;
						}
						else 
						{
							if (cur == prev->_left)
							{
								prev->_left = cur->_right;
							}
							else
							{
								prev->_right = cur->_right;
							}
						}
						delete cur;
						return true;
					}
					else if (cur->_right == nullptr)
					{
						if (cur == _root)
						{
							cur = cur->_left;
						}
						else
						{
							if (cur == prev->_left)
							{
								prev->_left = cur->_left;
							}
							else
							{
								prev->_right = cur->_left;
							}
						}
						delete cur;
						return true;
					}
					else
					{
						Node* RightMinParent = cur;
						Node* RightMin = cur->_right;
						while (RightMin->_left)
						{
							RightMinParent = RightMin;
							RightMin = RightMin->_left;
						}
						cur->_key = RightMin->_key;
						if (RightMin == RightMinParent->_left)
						{
							RightMinParent->_left = RightMin->_right;
						}
						else
						{
							RightMinParent->_right = RightMin->_right;
						}

						delete RightMin;
						return true;
					}
				}
			}
			return false;
		}
		void Inoder()
		{
			inoderprint(_root);
			cout << endl;
		}
		void inoderprint( Node* root)
		{
			if (root == nullptr)
			{
				return;
			}
			inoderprint(root->_left);
			cout << root->_key << " " << root->_value << endl;
			inoderprint(root->_right);
		}
	private:
		Node* _root = nullptr;
	};



}

以上实现是 KV模型:

可以使用以下代码测试功能:

#define  _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
#include"BSTree.h"


int main()
{
	key_value::BSTree<string, int> BST;
	BST.Insert("苹果",12);
	BST.Insert("梨",10);
	BST.Insert("草莓",9);
	BST.Insert("橘子",11);
	BST.Inoder();
	BST.Erase("梨");
	BST.Inoder();

	key_value::BSTreeNode<string,int> *node=BST.Find("苹果");
	cout << node->_key << " " << node->_value << endl;
	return 0;
}

  • 24
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值