【C++】BST树(二叉搜索树)

二叉搜索树

二叉树的意义是:任何节点最多只允许有两个子节点。这两个子节点被称为左子节点和右子节点。如果从递归的角度来看二叉树的话,二叉树可以被描述成:一个二叉树如果不为空,那么这棵二叉树便是由一个根节点和左右两棵子树构成;左右子树都可能为空。

所谓的二叉搜索树(binary search tree),在二叉树的基础上又升级了要求,二叉搜索树的节点放置规则是:任何节点的键值一定大于其左子树中每一个节点的键值,且一定小于其右子树中的每一个节点的键值。所以对二叉搜索树来说,从根节点一直往左走,直至无路可走,得到的就是该树的最小元素;从根节点一直往右走,直至无路可走,得到的就是该树的最大元素。

二叉搜索树中元素的插入和移除相对麻烦,原因是不能随意的插入和移除,要保证满足二叉搜索树的节点放置规则。

插入新元素时,从根节点开始,遇到键值较大者就向它的左边走,遇到键值较小的就向它的右边走,一直到尾端,即为插入点。

移除旧节点时,分四种情况,第一种是该节点有左子树也有右子树;第二种是该节点是叶子节点,也就是说该节点无孩子节点;第三种是该节点有左子树无右子树;第四种是该节点无左子树有右子树。在代码实现的时候,只需要分两种情况讨论即可,后三种统一处理,第一种单独处理,不过第一种最后也是转化为后三种进行处理的。

BST树的模拟实现:

template<class Type>
class BST;

template<class Type>
class BSTNode
{
	friend class BST<Type>;//声明友元类
public:
	BSTNode(Type d = Type(),BSTNode<Type>*left=nullptr,
		BSTNode<Type>*right=nullptr)
		:data(d),leftchild(left),rightchild(right)
	{}
	~BSTNode()
	{}
private:
	Type data;
	BSTNode<Type> *leftchild;
	BSTNode<Type> *rightchild;
};

template<class Type>
class BST
{
public:
	BST():root(nullptr)
	{}
	~BST()
	{
		Destroy(root);
	}
	void Destroy(BSTNode<Type> *&t)
	{
		if (t != nullptr)
		{
			Destroy(t->leftchild);
			Destroy(t->rightchild);
			delete t;//释放t指针
			t = nullptr;//将t赋空,预防野指针
		}
	}
public:
	bool Insert(const Type &v)
	{
		return Insert(root, v);
	}
	bool Remove(const Type &v)
	{
		return Remove(root, v);
	}
	BSTNode<Type>* Find(const Type& key)const//不允许修改
	{
		return Find(root, key);
	}
	Type Min()const
	{
		return Min(root);
	}
	Type Max()const
	{
		return Max(root);
	}
	void SortPrint()const
	{
		SortPrint(root);
		cout << endl;
	}
protected:
	bool Insert(BSTNode<Type> *&t, const Type &v)
	{
		//非递归实现
		//查找插入位置
		BSTNode<Type> *p = t, *pr = nullptr;
		while (p != nullptr)
		{
			if (v == p->data)
				return false;

			pr = p;
			if (v < t->data)
				p = p->leftchild;
			else
				p = p->rightchild;
		}
		
		p = new BSTNode<Type>(v);
		//建立连接  两种情况:构建新树 插入节点
		if (pr == nullptr)
		{
			t = p;
			return true;
		}
		if (v < pr->data)
			pr->leftchild = p;
		else
			pr->rightchild = p;
		return true;
	}

	bool Remove(BSTNode<Type>*&t, const Type &key)
	{
		//查找节点
		if (t == nullptr)
			return false;
		if (key < t->data)
			Remove(t->leftchild, key);
		else if(key > t->data)
			Remove(t->rightchild, key);

		else
		{
			//删除节点
			if (t->leftchild != nullptr && t->rightchild != nullptr)
			{
				BSTNode<Type> *p = t->leftchild;
				while (p->rightchild != nullptr)
					p = p->rightchild;//找到左子树最右的节点代替t

				t->data = p->data;
				Remove(t->leftchild, p->data);//删除左子树中最右的节点
			}
			else
			{
				//最多只有一颗子树 叶节点 左空右不空 右空左不空
				BSTNode<Type> *p = t;//t是要删除的节点位置
				if (t->leftchild != nullptr)
					t = p->leftchild;
				else
					t = p->rightchild;
				delete p;
			}
			return true;
		}
	}

	void SortPrint(BSTNode<Type> *t)const
	{
		if (t != nullptr)
		{
			SortPrint(t->leftchild);
			cout << t->data << " ";
			SortPrint(t->rightchild);
		}
	}

	Type Min(BSTNode<Type>*t)const
	{
		//断言树不为空
		assert(t != nullptr);
		while (t->leftchild != nullptr)
		{
			t = t->leftchild;
		}
		return t->data;
	}

	Type Max(BSTNode<Type>*t)const
	{
		assert(t != nullptr);
		while (t->rightchild != nullptr)
			t = t->rightchild;
		return t->data;
	}

	BSTNode<Type>* Find(BSTNode<Type>*t, const Type& key)const
	{
		if (t == nullptr || t->data == key)
			return t;

		if (key < t->data)
			return Find(t->leftchild, key);
		else
			return Find(t->rightchild, key);
	}
private:
	BSTNode<Type> *root;
};

主函数代码测试:

int main()
{
	vector<int> v={ 18,14,12,16,15,20 };
	BST<int> bst;
	for (int i = 0; i < v.size(); ++i)
	{
		bst.Insert(v[i]);
	}
	bst.SortPrint();
	bst.Remove(1);
	bst.SortPrint();
	BSTNode<int>* it = bst.Find(20);
	cout << bst.Max() << endl;
	cout << bst.Min() << endl;
	return 0;
}

执行结果:

12 15 14 18 20
12 15 14 18 20
20
12
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值