C++二叉搜索树(插入_删除(替换法)_查找_遍历_二叉搜索树检查)_二叉链递归与三叉链非递归

1.二叉链形式递归

#pragma once
#include<iostream>

using namespace std;

template<class Key,class Value>
struct BSTreeNode
{
	BSTreeNode<Key,Value>* _left;
	BSTreeNode<Key,Value>* _right;
	Key _key;
	Value _val;
	BSTreeNode(const Key& key, const Value& val)
		:_left(nullptr), _right(nullptr), _key(key), _val(val)
	{}
};

namespace MyR_KeyValue
{
	template<class Key,class Value>
	class BSTree
	{
		typedef BSTreeNode<Key,Value> Node;
	public:
		BSTree()
			:_root(nullptr)
		{}

		~BSTree()
		{
			Destory();
			_root = nullptr;
		}

		//拷贝构造函数(深拷贝)
		BSTree(const BSTree<Key,Value>& dev)
		{
			_root = _Copy(dev._root);
		}

		//赋值运算符重载
		BSTree<Key,Value>& operator=(BSTree<Key,Value> dev)
		{
			swap(_root, dev._root);
			return *this;
		}

		//节点查找
		Node* Find(const Key& key)
		{
			return _Find(_root, key);//体现了封装,简化用户使用,这里选择嵌套一层,这个最好函数被修饰为私有
		}

		//节点插入
		bool Insert(const Key& key,const Value&val)
		{
			return _Insert(_root, key, val);
		}

		//节点中序打印
		void PrintBSTree()
		{
			_PrintBSTree(_root);
			cout << endl;
		}

		bool Erase(const Key& key)
		{
			return _Erase(_root, key);
		}

		void Destory()
		{
			_Destory(_root);
		}
	private:
		Node* _root;



		bool _Erase(Node*& root, const Key& key);//声明

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

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

		bool _Insert(Node*& root, const Key& key, const Value& val)
		{
			if (root == nullptr)
			{
				root = new Node(key, val);//root是root->left别名相当于root->left=new BSTreeNode(key)
				return true;
			}

			if (root->_key > key)
			{
				_Insert(root->_left, key, val);
			}
			else if (root->_key < key)
			{
				_Insert(root->_right, key, val);
			}
			else//数字相同,不做处理
			{
				return false;
			}
		}

		void _PrintBSTree(Node* root)//中序遍历左子树->节点->右子树
		{
			if (root == nullptr)
				return;
			if (root->_left)
				_PrintBSTree(root->_left);
			cout << root->_key << ":" << root->_val << endl;
			if (root->_right)
				_PrintBSTree(root->_right);
		}

		void _Destory(Node* root)//后序遍历销毁
		{
			if (root == nullptr)
				return;
			_Destory(root->_left);
			_Destory(root->_right);
			delete root;
		}

		Node* _Copy(Node* root)
		{
			if (root == nullptr)
				return nullptr;
			Node* CopNode = new Node(root->_key,root->_val);
			CopNode->_left = _Copy(root->_left);
			CopNode->_right = _Copy(root->_right);
			return CopNode;
		}
	};
}

template<class Key,class Value>
bool MyR_KeyValue::BSTree<Key,Value>::_Erase(Node*& root, const Key& key)
{
	if (root == nullptr)//没找到对应的位置
	{
		return false;
	}

	if (root->_key > key)
	{
		_Erase(root->_left, key);
	}
	else if (root->_key < key)
	{
		_Erase(root->_right, key);
	}
	else //找到要删除的位置
	{
		if (root->_left == nullptr)
		{
			Node* del = root;
			root = root->_right;//root是父节点的叶节点的引用相当于root->left=root->left->right;
			delete del;
		}
		else if (root->_right == nullptr)
		{
			Node* del = root;
			root = root->_left;
			delete del;
		}
		else //左右节点都不为空(替换法)
		{
			Node* minRight = root->_right;
			while (minRight->_left)
			{
				minRight = minRight->_left;
			}
			Key tmp = minRight->_key;//先保存右子树的最小值
			Value val = minRight->_val;
			_Erase(root->_right, tmp);//递归删除右子树的最小值
			root->_key = tmp;//将右子树的最小值赋给要删除节点
			root->_val = val;
			return true;
		}
	}
}


2.三叉链形式+动态插入动态删除过程_非递归

#include<iostream>
#include<ctime>
#include<cstdlib>
#include<vector>
#include<Windows.h>
using namespace std;

//三叉链,这里插入方式按照搜索二叉树key模型的插入规则来实现
template<class key>
struct BSTNode
{
	BSTNode* left;
	BSTNode* right;
	BSTNode* parent;
	key val;
	BSTNode(const key& _val) :left(nullptr), right(nullptr), parent(nullptr), val(_val) {}
};

template<class key>
class BSTree
{
public:
	typedef BSTNode<key> Node;

	BSTree() :Head(nullptr) {}

	~BSTree()
	{
		_Deleat(Head);
	}

	//拷贝构造函数
	BSTree(const BSTree<key>&dev)//前序构造
	{
		Head=_Copy(dev.Head);
	}

	//赋值运算符重载
	BSTree<key>& operator =(const BSTree<key>& dev)
	{
		BSTree<key>copy(dev);
		std::swap(Head, copy.Head);
		return *this;
	}

	//插入二叉树,不允许插入相同的值
	bool Insert(const key& _val)
	{
		if (Head == nullptr)
		{
			Head = new Node(_val);
			return true;
		}
		else
		{
			Node* tmp = Head;
			Node* Bef = nullptr;
			while (tmp != nullptr)
			{
				if (tmp->val > _val)
				{
					Bef = tmp;
					tmp = tmp->left;
				}
				else if (tmp->val < _val)
				{
					Bef = tmp;
					tmp = tmp->right;
				}
				else//找到相同的值
				{
					cout << "数字重复" << endl;
					return false;
				}
			}
			Node* cur = new Node(_val);
			cur->parent = Bef;
			if (Bef->val > _val)
			{
				Bef->left = cur;
			}
			else
			{
				Bef->right = cur;
			}
			return true;
		}
	}

	bool IsRightTree()//判断是否是搜索二叉树
	{
		return _IsRightTree(Head,GetMin(),GetMax());
	}

	//查找节点,返回节点指针
	Node* Find(const key& pos)
	{
		Node* find = Head;
		while (find != nullptr)
		{
			if (find->val > pos)
			{
				find = find->left;
			}
			else if (find->val < pos)
			{
				find = find->right;
			}
			else //找到了
			{
				return find;
			}
		}
		cout << "树中无此数字" << endl;
		return find;
	}

	//通过节点的数字删除节点
	bool DeleteNode(const key& val)
	{
		return _DeleatNode(Head, val);
	}

	//中序打印二叉树
	void PrintTree()
	{
		if (Head == nullptr)
		{
			cout<<"树为空"<<endl;
			return;
		}
		_PrintTree(Head);
		cout << endl;
	}
private:
	Node* Head;

	Node* _Copy(Node* cur)//拷贝构造函数,前序遍历
	{
		Node* NewHead = nullptr;
		if (cur != nullptr)
		{
			NewHead = new Node(cur->val);
			NewHead->left = _Copy(cur->left);
			NewHead->right = _Copy(cur->right);
		}
		return NewHead;
	}

	//树内置查找
	Node* _Find(Node* Tree, const key& val)
	{
		if (Tree == nullptr)
		{
			return nullptr;
		}
		Node* cur = Tree;
		while (cur!=nullptr)
		{
			if (cur->val > val)
			{
				cur = cur->left;
			}
			else if (cur->val < val)
			{
				cur = cur->right;
			}
			else
			{
				return cur;
			}
		}
		cout << "找不到节点" << endl;
		return nullptr;
	}

	const key GetMin()//获得树最小的数字
	{
		if (Head == nullptr)
		{
			cout << "树为空,不存在最小值" << endl;
			return 0;
		}
		else
		{
			Node* cur = Head;
			while (cur->left != nullptr)
			{
				cur = cur->left;
			}
			return cur->val;
		}
	}

	const key GetMax()//获得树最大的数字
	{
		if (Head == nullptr)
		{
			cout << "树为空,不存在最小值" << endl;
			return 0;
		}
		else
		{
			Node* cur = Head;
			while (cur->right != nullptr)
			{
				cur = cur->right;
			}
			return cur->val;
		}
	}

	//查每个节点能取的最大最小值是否满足
	bool _IsRightTree(Node* Head, const key& min, const key& max)
	{
		if (Head == nullptr || Head->val == 0)
		{
			return true;空节点也是二叉搜索树
		}
		else if (Head->val<min || Head->val>max)
		{
			return false;
		}
		return _IsRightTree(Head->left, min, Head->val - 1) && _IsRightTree(Head->right, Head->val + 1, max);
	}

	bool _DeleatNode(Node* Tree, const key& val)
	{
		Node* cur = _Find(Tree,val);
		if (cur == nullptr)
		{
			cout << "找不到数字,删除失败" << endl;
			return false;
		}
		//①要删除结点的左孩子为空或者右孩子为空
		if (cur->left == nullptr)//左孩子为空
		{
			//如果要删除的结点是根结点并且左孩子为空,替换根节点为右树根节点
			if (cur->parent == nullptr)
			{
				if (cur->right == nullptr)//一个节点
				{
					BSTree<int>tmp;
					std::swap(Head, tmp.Head);
					return true;
				}
				cur->right->parent = Head->parent;
				Head = cur->right;
				free(cur);
			}
			//不是根节点,则直接判断调整指向
			else
			{
				if (cur->right != nullptr)
				{
					cur->right->parent = cur->parent;//修改父节点
				}
				if (cur == cur->parent->left)
				{
					cur->parent->left = cur->right;
					free(cur);
				}
				else
				{
					cur->parent->right = cur->right;
					free(cur);
				}
			}
		}
		else if (cur->right == nullptr)
		{
			//如果要删除的结点是根结点并且右孩子为空,替换根节点为左树根节点
			if (cur->parent == nullptr)
			{
				if (cur->left == nullptr)
				{
					BSTree<int>tmp;
					std::swap(Head, tmp.Head);
					return true;
				}
				cur->left->parent = Head->parent;
				Head = cur->left;
				free(cur);
			}
			//不是根节点,则直接判断调整指向
			else
			{
				if (cur->left != nullptr)
				{
					cur->left->parent = cur->parent;
				}
				if (cur == cur->parent->left)
				{
					cur->parent->left = cur->left;
					free(cur);
				}
				else
				{
					cur->parent->right = cur->left;
					free(cur);
				}
			}
		}
		//②要删除结点的左右孩子都不为空(替换删除法)
		else
		{
			Node* repalce = cur->right;
			//找到要替换的结点(要删除结点右树最左边的那个结点就是替换结点)
			while (repalce->left)
			{
				repalce = repalce->left;
			}
			//替换数据
			cur->val = repalce->val;
			//删除这个节点和上面的逻辑重复了,可以递归实现删除右树的这个值
			_DeleatNode(cur->right, repalce->val);
		}
		return true;
	}

	void _Deleat(Node*Head)//后序
	{
		if (Head == nullptr)
		{
			return;
		}
		_Deleat(Head->left);
		_Deleat(Head->right);
		free(Head);
	}
	void _PrintTree(Node* _head)//中序
	{
		if (_head == nullptr)
			return;
		_PrintTree(_head->left);
		cout << _head->val << " ";
		_PrintTree(_head->right);
	}
};

//单元测试
void Test1()//测试二叉搜索树的插入,删除,判断,打印接口;
{
	BSTree<int>T;
	T.Insert(10);
	T.Insert(1);
	T.Insert(1);
	T.Insert(3);
	T.Insert(11);
	T.PrintTree();
	if (T.Find(11) != nullptr && T.Find(10000) == nullptr)
	{
		cout << "查找函数正确" << endl;
	}
	else
	{
		cout << "查找函数不正确" << endl;
	}
	if (T.IsRightTree())
	{
		cout << "是二叉搜索树" << endl;
	}
	else
	{
		cout << "插入错误,不是二叉搜索树" << endl;
	}
	T.DeleteNode(10);
	T.DeleteNode(3);
	T.DeleteNode(11);
}

void MoveDeleat()
{
	srand((unsigned int)time(0));
	BSTree<int>Tree;
	int Max = rand() % 10 + 10;//10到19大小的数组
	vector<int>tmp;
	for (int i = 0; i < Max; i++)
	{
		int Num = rand() % 10 + 10;
		cout << "开始插入数据" << endl;
		if (Tree.Insert(Num))
		{
			Tree.PrintTree();
			if (Tree.IsRightTree())
			{
				cout << "插入正确,是二叉搜索树" << endl;
			}
			Sleep(500);
			tmp.push_back(Num);
		}
	}
	Sleep(1000);
	cout << "删除开始" << endl << endl;;
	Sleep(500);
	for (int i = 0; i < tmp.size(); i++)
	{
		Tree.PrintTree();
		Tree.DeleteNode(tmp[i]);
		Sleep(500);
	}
	cout << "删除成功" << endl;
}

int main()
{
	BSTree<int>Tree;
	int input = 0;
	int Num = 0;
	int falg = 0;
	while (1)
	{
		if (falg == 1)
		{
			cout << "退出成功" << endl;
			break;
		}
		cout << "1.插入 2.删除 3.打印 4.查找 5.判断是否是二叉搜索树 6.退出 7.动态演示删除过程" << endl;
		cin >> input;
		switch (input)
		{
		case 1:
			system("cls");
			cout << "输入要插入的值" << endl;
			cin >> Num;
			Tree.Insert(Num);
			system("cls");
			break;
		case 2 :
			system("cls");
			Tree.PrintTree();
			cout << "要删除的值" << endl;
			cin >> Num;
			Tree.DeleteNode(Num);
			break;
		case 3:
			system("cls");
			cout << "树的中序遍历如下" << endl;
			Tree.PrintTree();
			break;
		case 4:
			cout << "要查找的值" << endl;
			cin >> Num;
			if (Tree.Find(Num))
			{
				cout << "找到了" << endl;
			}
			break;
		case 5:
			if (Tree.IsRightTree())
			{
				cout << "是二叉搜索树" << endl;
			}
			else
			{
				cout << "树结构错误" << endl;
			}
			break;
		case 6:
			falg = 1;
			break;
		case 7:
			cout << "随机数组动态删除如下" << endl;
			MoveDeleat();
			break;
		default:
			break;
		}
	}
	return 0;
}

运行结果

在这里插入图片描述

二叉搜索树删除节点思路

二叉搜索树的删除节点思路

上面的链接写的很清楚,不在赘述了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

NUC_Dodamce

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

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

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

打赏作者

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

抵扣说明:

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

余额充值