二叉搜索树的代码详解

目录

1.binary_search_tree

2.测试函数

3.判断一颗树是否是搜索二叉树


1.binary_search_tree

#define _CRT_SECURE_NO_WARNINGS 1

#include<iostream>
using namespace std;
namespace LRT {

	template<class K, class V>
	struct BSNode
	{
		BSNode<K, V>* _left;
		BSNode<K, V>* _right;
		K _key;
		V _val;
		BSNode()
			:_left(nullptr),
			_right(nullptr),
			_key(0),
			_val(0)
		{}

		BSNode(const  K& key = 0, const V& val = 0)
			:_left(nullptr),
			_right(nullptr),
			_key(key),
			_val(val)
		{}
	};


	template<class K, class V>
	class binary_search_tree {
	private:
		BSNode<K, V>* _root;
		typedef BSNode<K, V> node;

	public:
		binary_search_tree(void)
			:_root(nullptr)
		{

		}

		bool insert(const K& key, const V& val) {
			return _insert(key, val, _root);
		}
	private:
		bool _insert(const K& key, const V& val, node*& cur) { //传引用的得到的指针,直接修改指向,就是修改树上结点的连接2方式
			if (cur == nullptr)
			{
				cur = new node(key, val);
				return true;
			}

			if (key < cur->_key)
			{
				if (cur->_left == nullptr)
				{
					node* new_node = new node(key, val);
					cur->_left = new_node;
					return true;
				}
				return _insert(key, val, cur->_left);
			}

			if (key > cur->_key)
			{
				if (cur->_right == nullptr)
				{
					node* new_node = new node(key, val);
					cur->_right = new_node;
					return true;
				}
				return _insert(key, val, cur->_right);
			}

			if (key == cur->_key)
			{
				return false;
			}
		}
	public:
		void printf_bst(void) {
			_printf_bst(_root);
		}
	private:
		void _printf_bst(node* cur)
		{
			if (cur == nullptr)
			{
				return;
			}

			_printf_bst(cur->_left);
			cout << cur->_key << "  " << cur->_val << endl;
			_printf_bst(cur->_right);
		}
	public:
		node* find(const K& key) {
			node* cur = _root;
			while (cur) {
				if (key < cur->_key) {
					cur = cur->_left;
				}
				else if (key > cur->_key) {
					cur = cur->_right;
				}
				else if(key == cur->_key) {//只写else的时候报了个内部编译的错误,可以一段段屏蔽,自己看看哪里有错误,毕竟这个报错报的一头雾水
					return cur;
				}
			}
			return nullptr;
		}

		bool erase_by_max_left(const K& key)//左树的最大节点除了根一定是其他节点的右子树
		{
			return _erase_by_max_left(_root, key);
		}
		private:

			bool _erase_by_max_left(node*& cur, const K& key) {//此处必须传引用,因为要需修改当前节点
				if (cur == nullptr) {
					return false;
				}
				
				if(key<cur->_key){
					return _erase_by_max_left(cur->_left,key);
				}

				else if (key > cur->_key) {
					return _erase_by_max_left(cur->_right, key);
				}
				else {//找到了,开始准备删除
					//如果左右字数有一颗为空,那么直接托孤
					node* del = cur;//把原本正在维护的指向需要删除节点的的指针先拷贝一份,后面需要进行删除。
					if (cur->_right == nullptr) {
						cur = cur->_left;
					}


					else if (cur->_left == nullptr) {
						cur = cur->_right;
					}

					else {	 //与其左子树最大值交换后递归下去删除该节点
						node* max_left =cur->_left;//开始找该节点左子树的最大的节点
						while (max_left->_right) {
							max_left = max_left->_right;
						}

						swap(max_left->_key, cur->_key);
						swap(max_left->_val, cur->_val);

						return _erase_by_max_left(cur->_left, key);
					}
					delete del;
					return true;
				}
			}

			public:
				bool erase_by_min_right(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
						{
							// 1、左为空
							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、右为空
							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;
							}
							else
							{
								// 找右树最小节点替代,或左树最大节点
								node* parent_minRight = cur;
								node* minRight = cur->_right;
								while (minRight->_left)
								{
									parent_minRight = minRight;
									minRight = minRight->_left;
								}

								cur->_key = minRight->_key;

								if (parent_minRight->_left == minRight)
								{
									parent_minRight->_left = minRight->_right;
								}
								else
								{
									parent_minRight->_right = minRight->_right;
								}

								delete minRight;
							}

							return true;
						}
					}

					return false;
				}
	};

}

2.测试函数

test.c

void test()
{
	//LRT::BSNode<int, int>* root = nullptr;
	LRT::binary_search_tree<int,int> BST;
	BST.insert(-13, 1);
	BST.insert(-11, 1);
	BST.insert(-89, 1);
	BST.insert(-32, 1);
	BST.insert(-44, 1);
	BST.insert(1, 1);
	BST.insert(1, 1);
	BST.insert(2, 1);
	BST.insert(3, 1);
	BST.insert(7, 1);
	BST.insert(14, 1);
	BST.insert(12, 1);
	BST.insert(7, 1);
	BST.printf_bst();

	cout << endl;
	//auto ret= BST.find(7);
	//if (ret)
	//{
	//	cout << ret->_key << "  " << ret->_val << endl;
	//}

	//ret = BST.find(-44);
	//if (ret)
	//{
	//	cout << ret->_key << "  " << ret->_val << endl;
	//}

	BST.erase_by_max_left(1);

	BST.printf_bst();
	cout << endl;
	BST.erase_by_max_left(-89);

	BST.printf_bst();
	cout << endl;
}

void test2()
{
	int arr[15] = { 1,2,4,6,-3,-78,65,98 ,- 40,33,23,-45,-6,-31,45 };
	int arr2[15] = { 1,2,4,6,-3,-78,65,98 - 40,33,23,-45,-6,-31,45 };
	LRT::binary_search_tree<int, int> BST;
	for (int i = 0; i < 15; i++)
	{
		BST.insert(arr[i], arr[i]);
	}
	BST.printf_bst();
	cout << endl;

	//for (int i = 0; i < 15; i++)
	//{
	//	BST.erase_by_max_left(arr[i]);
	//	BST.printf_bst();
	//	cout << endl;
	//}

	for (int i = 14; i >=0; i--)
	{
		BST.erase_by_max_left(arr[i]);
		BST.printf_bst();
		cout << endl;
	}
	cout << endl;
}

void test3() {
		int arr[15] = { 1,2,4,6,-3,-78,65,98 ,-40,33,23,-45,-6,-31,45 };
		int arr2[15] = { 1,2,4,6,-3,-78,65,98 - 40,33,23,-45,-6,-31,45 };
		LRT::binary_search_tree<int, int> BST;
		for (int i = 0; i < 15; i++)
		{
			BST.insert(arr[i], arr[i]);
		}
		BST.printf_bst();
		cout << endl;

		//for (int i = 0; i < 15; i++)
		//{
		//	BST.erase_by_max_left(arr[i]);
		//	BST.printf_bst();
		//	cout << endl;
		//}

		for (int i = 14; i >= 0; i--)
		{
			BST.erase_by_min_right(arr[i]);
			BST.printf_bst();
			cout << endl;
		}
		cout << endl;
}

int main()
{
	//test2();
	test3();
}

3.判断一颗树是否是搜索二叉树

判断一棵二叉树是否为「二叉搜索树」的通用方法为:对该二叉树进行中序遍历,若遍历结果为「严格」单调递增的,则是一棵二叉搜索树,否则不是。

  • 14
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 11
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

葬送的代码

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值