二叉搜索树

数值规定:

节点左边的比节点值小,右边的比节点大

特点:

1.中序遍历有序。(整体是有序的左边的树一定都比节点小,右边的一定比节点大。因为插入时通过遍历按照此规则找到位置新增节点)

2.搜索最多找高度次。

3.不能修改,修改后需重新排序,只能增删方便

#include<iostream>
using namespace std;
template <class T>
class BSTNode
{
public:
	BSTNode<T> * _left;//记得加<T>
	BSTNode<T> * _right;
	T _key;
	//传参允许const允许传临时变量,用引用避免拷贝传参,缺省值给临时变量可以外部省去传参,直接构成数组,直接new
	BSTNode(const T&key = T() )//BSTNode(T key)
		:_key(key), _left(nullptr), _right(nullptr)
	{}
};
template<class T>//用模板类要有参数列表
class BSTree
{
	typedef BSTNode<T> Node;
	
	Node* root = nullptr;
	static void InOrderFind(Node* pcur)
	{
		if (pcur == nullptr)
			return;
		InOrderFind(pcur->_left);
		cout << pcur->_key << " ";
		InOrderFind(pcur->_right);
	}
public:
	bool Insert(T key)
	{
		if (root == nullptr)
		{
			root = new Node(key);
			return true;
		}
		else
		{
			Node* cur = root;
			Node* parent = nullptr;
			while (cur)
			{
				parent = cur;
				if (cur->_key > key)
				{
					cur = cur->_left;
				}
				else if (cur->_key < key)
				{
					cur = cur->_right;
				}
				else
					return false;
			}
			if (parent->_key>key)
			{
				parent->_left = new Node(key);
			}
			else
			{
				parent->_right = new Node(key);
			}
		}
	}
	void InOrderFind()//缺省参数只能缺省常量或全局变量
	{
		InOrderFind(root);
	}
	bool Erase(T key)
	{
		if (root == nullptr)
			return false;
		Node* cur = root;
		Node* parent = nullptr;
		while (cur)//最多找到空,找到就删掉返回true结束
		{	
			if (cur->_key > key)
			{
				parent = cur;//父节点更新在子节点更新前
				cur = cur->_left;
			}
			else if (cur->_key < key)
			{
				parent = cur;
				cur = cur->_right;
			}
			else
			{
				//删掉的有0,1个子节点
				if (cur->_left == nullptr)
				{
					if (parent == nullptr)//删只有0,1子节点的根节点,没有父节点
					{
						Node* delnode = root;
						root = root->_right;
						delete delnode;
						return true;
					}
					//他的位置在左还是右
					if (parent->_left == cur)
					{
						parent->_left = cur->_right;
					}
					else
					{
						parent->_right = cur->_right;
					}
					delete cur;
				}
				else if (cur->_right == nullptr)
				{
					if (parent == nullptr)
					{
						Node* delnode = root;
						root = root->_left;
						delete delnode;
						return true;
					}
					if (parent->_left == cur)
					{
						parent->_left = cur->_left;
					}
					else
					{
						parent->_right = cur->_left;
					}
					delete cur;
				}
				else//两个节点位置
				{
					//找比节点右边小比左边大的
					//找右边最小或左边最大
					Node* dparent = cur;
					Node* dnode = cur->_right;
					while (dnode->_left)
					{
						dparent = dnode;
						dnode = dnode->_left;
					}
					//右边最小就是节点右边
					if (dnode == dparent->_right)
					{
						cur->_key = dnode->_key;
						dparent->_right = dnode->_right;
						delete dnode;
					}
					else
					{
						cur->_key = dnode->_key;
						dparent->_left = dnode->_right;
						delete dnode;
					}
				}
				return true;
			}
		}
		return false;
	}
};
int main()
{
	int a[10] = { 1,4,2,7,3,1,45,7,3,8 };
	typedef BSTree<int> BSTreeI;
	BSTreeI bstree;
	for (auto e : a)
	{
		bstree.Insert(e);
	}
	for (auto e : a)
	{
		bstree.Erase(e);
		bstree.InOrderFind();
		cout << endl;
	}
	return 0;
}

构成:同链表,先创建子节点的模板类,记录值和左右子节点,再创建二叉搜索树,包含根节点,至少提供增加和删除和中序遍历。

增加:因为其有序,直接循环遍历,比值大走有,小走左,遍历到空节点插入,额外提前检查是不是空树。

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

删除:首先查找元素是否在二叉搜索树中,如果不存在,则返回找到其位置

删除要记录对应节点位置前的父节点,以便让父节点对下面节点操作:分为

1.要删除节点是含0,1子节点的,判断是不是根节点(根节点没有找到的父节点)是删除返回,父节点直接接入有的那一节点 

2.要删除节点含2个子节点,删除这个节点并保持大致结构不变思路是:找到比此节点左子树大,右子树小的节点,即左子树的最右(最大),右子树的最左(最小)节点。同样找到后要删除这个节点,所以要记录其父节点,找到后因为其是最左/最有节点,一定只含0/1个子节点,父节点连接应有的子节点,原要删除节点获取值并删除找到的最节点即可。

补充:

记录并保持其父节点关键是一开始就将父节点变量设为此节点的父,没有设nullptr,然后在每次此节点变化代码前父节点获取此节点的值。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值