二叉搜索树

二叉搜索树又称二叉排序树,它或者是一棵空树或者是具有以下性质的二叉树:
1.若它的左子树不为空,则左子树上所有节点的值都小于根节点的值。
2.若它的右子树不为空,则右子树上所有节点的值都大于根节点的值。
3.它的左右子树也分别为二叉搜索树。

1. 节点的类

template<class T,class V = int>   // 第二个模板可以不使用,用于记录key对应的某个数据
 struct Node
{
	Node<T,V>* _left;
	Node<T,V>* _right;
	T _key;
	V _value;
	Node(const T& key=T(),const V& value=V())
	{
		_left = nullptr;
		_right = nullptr;
		_key = key;
		_value = value;
	}
};

2. 插入函数

	bool Insert(const T& key=T(), const V& value=V())   //  全缺省,方便只需要一个模板存储key的时候
	{


		if (_pnode == nullptr)
		{
			_pnode = new Node(key,value);
			return true;
		}


		//  找正确的位置,将key插入底层
		Node* root = _pnode;
		Node* prev = nullptr;   // prev记录root的父节点 , 当root为空是,对prev的left或right开辟空间,将key插入
		while (root != nullptr)
		{
			if (root->_key == key)
			{
				return false;   // 不允许重复的数出现
			}
			if (root->_key > key)
			{
				prev = root;
				root = root->_left;
			}
			else
			{
				prev = root;
				root = root->_right;
			}
		}

		//  root==nullptr结束
		if (prev->_key>key)
		{
			prev->_left = new Node(key,value);
		}
		else
		{
			prev->_right = new Node(key,value);
		}
		return true;
	}

3.查找函数

	Node* _Find(Node* root, const T& key)
	{
		if (root == nullptr)
		{
			return nullptr;
		}

		if (key == root->_key)
		{
			return root;
		}
		else if (key < root->_key)
		{
			return _Find(root->_left, key);
		}
		else
		{
			return _Find(root->_right, key);
		}
	}

	Node* Find(const T& key)     // 为什么需要再创建一个函数,因为 this指针是隐藏的,无法在形参里面直接调用this->_pnode
	{
		return _Find(_pnode, key);
	}

4.删除函数

	bool Erase(const T& key)
	{
		if (_pnode == nullptr)
		{
			return false;
		}
		//找到key对应的位置
		//需要一个prev指针记录key的父节点,这样可以用prev直接连接key的子节点

		Node* prev = nullptr;
		Node* cur = _pnode;

		while (cur != nullptr)
		{
			if (key == cur->_key)
			{
				break;
			}
			else if (key < cur->_key)
			{
				prev = cur;
				cur = cur->_left;
			}
			else
			{
				prev = cur;
				cur = cur->_right;
			}
		}

		if (cur == nullptr)
		{
			return false;
		}


		//  cur==_pnode  并且左右至少有一个为空  
		//  因为当 cur ==  _ponde  prev无法处理,需要单独拿出讨论
		if (cur == _pnode)
		{
			if (cur->_left == nullptr)
			{
				_pnode = cur->_right;
				delete cur;
				return true;
			}
			if (cur->_right == nullptr)
			{
				_pnode = cur->_left;
				delete cur;
				return true;
			}
		}


		//  cur != _pnode   或   cur== _pnode 且两边均不为nullptr
		if (cur->_left == nullptr)
		{
			if (prev->_left == cur)
			{
				prev->_left = cur->_right;
			}
			else
			{
				prev->_right = cur->_right;
			}
			delete cur;
			return true;
		}

		if (cur->_right == nullptr)
		{
			if (prev->_left == cur)
			{
				prev->_left = cur->_left;
			}
			else
			{
				prev->_right = cur->_left;
			}
			delete cur;
			return true;
		}



		//   当两边都不为空时,这时不需要prev
		// 需要找cur左子树的最大只或右子树的最小值去代替cur的key

		if (cur->_left != nullptr && cur->_right != nullptr)
		{
			//找右边的最小值
			Node* rightmin = cur->_right;
			Node* rightprev = cur;

			if (rightmin->_left == nullptr)  // cur->right就是右边最小的数
			{
				rightprev->_right = rightmin->_right;
			}
			else
			{
				while (rightmin->_left)
				{
					rightprev = rightmin;
					rightmin = rightmin->_left;     //  一直往左移找到最小的数
				}
				//当rightmin->left=nullptr  时就找到了

				cur->_key = rightmin->_key;
			}
			rightprev->_left = rightmin->_right;  // right可能还有右子树
			delete rightmin;
			return true;
		}
	}

5.中序遍历

	void Pushstack(Node* root,stack<Node*>& s)    //  传引用 !!!
	{
		while (root != nullptr)
		{
			s.push(root);
			root = root->_left;
		}
	}

	void _InOrder(Node* _pnode)
	{
		stack<Node*> s;
		Pushstack(_pnode, s);
		while (!s.empty())
		{
			Node* _top = s.top();
			cout << _top->_key << " ";
			s.pop();
			Pushstack(_top->_right, s);
		}
	}

	void InOrder()
	{
		this->_InOrder(_pnode);
		cout << endl;
	}

6.测试

void test1()
{
	int arr[] = { 2,4,6,1,32,57,21,23,44,37 };
	BSTree<int,int> root;
	for (auto a : arr)
	{
		root.Insert(a);
	}
	root.InOrder();

	root.Erase(6);
	root.InOrder();
	root.Erase(4);
	root.InOrder();
	root.Erase(32);
	root.InOrder();
	root.Erase(57);
	root.InOrder();
	root.Erase(44);
	root.InOrder();
	root.Erase(37);
	root.InOrder();
	root.Erase(23);
	root.InOrder();
	root.Erase(1);
	root.InOrder();
	root.Erase(2);
	root.InOrder();
	root.Erase(21);
	root.InOrder();
}

结果:
1 2 4 6 21 23 32 37 44 57
1 2 4 21 23 32 37 44 57
1 2 21 23 32 37 44 57
1 2 21 23 37 44 57
1 2 21 23 37 44
1 2 21 23 37
1 2 21 23
1 2 21
2 21
21




//  需要将中序遍历的cout改一下

cout << _top->_key <<_top->_value << "个"  << endl;

//
void test3()
{
	string arr[] = { "苹果", "西瓜", "苹果", "西瓜", "苹果", "苹果", "西瓜",
"苹果", "香蕉", "苹果", "香蕉" };
	BSTree<string, int> counttree;
	for (auto a : arr)
	{
		Node<string, int>* ret = counttree.Find(a);
		if (ret)
		{
			ret->_value++;
		}
		else
		{
			counttree.Insert(a, 1);
		}
	}
	counttree.InOrder();
}



结果:
苹果6个
西瓜3个
香蕉2个



void test2()
{
	BSTree<string, string> dict;
	dict.Insert("string", "字符串");
	dict.Insert("tree", "树");
	dict.Insert("left", "左边、剩余");
	dict.Insert("right", "右边");
	dict.Insert("sort", "排序");
	// 插入词库中所有单词
	string str;
	while (cin >> str)
	{
		Node<string,string>* ret = dict.Find(str);
		if (ret == nullptr)
		{
			cout << "单词拼写错误,词库中没有这个单词:" << str << endl;
		}
		else
		{
			cout << str << "中文翻译:" << ret->_value << endl;
		}
	}
}


结果:
string
string中文翻译:字符串
right
right中文翻译:右边
sort
sort中文翻译:排序
left
left中文翻译:左边、剩余
AMR
单词拼写错误,词库中没有这个单词:AMR
AWM
单词拼写错误,词库中没有这个单词:AWM

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值