二叉查找树

二叉查找树(二叉搜索 / 排序树):

前情提要:因为蒟蒻所以就写个伪代码,代码后续补上(好难写呜呜呜还是编辑器用的不太熟练)

一:定义
是一颗空树或者是具有下列性质的树:
(1)若任意节点的左子树非空,则左子树上所有的结点的值都小于它的根结点的值。
(2)若任意节点的右子树非空,则右子树上所有的结点的值都大于它的根节点的值。
(3)左右子树都是二叉搜索树。
(4)树中的每个节点的值都不相同。(有需要也可以将相同的值插入树中)

二:基本操作
基本操作有:遍历(walk),查找(search),最小 / 最大关键字(minimum / maximum)
后继 / 前驱 , 插入 / 删除。

0.搜索树的结点。
	包含左孩子指针lchild,
	右孩子指针rchild,
	父节点指针parent,
	关键值key。
	定义一个节点类bst来表示结点。
class Bst
{
	private:
		Bst *lchild;//left
		Bst *rchild;//right
		Bst *parent;//父节点
		int key;//关键字
		friend class bstree;
	public:
		Bst(int k=0,Bst *l=NULL,Bst *r=NULL,Bst *p=NULL)
		{
			key=k;
			lchild=l;
			rchild=r;
			parent=p;
		}
};
1.遍历(walk)
	分为先序,中序,后序遍历。
	
		先序:根节点—>左子树—>右子树。
		中序:左子树—>根节点—>右子树。
		后序:左子树—>右子树—>根节点。
		
	先序遍历:通过递归实现。输出的关键字在其左右子树之前
		伪代码:
		prewalk(x)
			if(x!=NULL)
			{
				printf  x->key;
				prewalk(x->lchild);
				prewalk(x->rchild);
			}
	中序遍历:同理,输出的关键字在左右子树中间
		伪代码:
		midwalk(x)
			if(x!=NULL)
			{
				midwalk(x->lchild);
				printf x->key;
				midwalk(x->rchild);
			}
	后序遍历:
		伪代码:
		powalk(x)
		if(x!=NULL)
			{
				powalk(x->lchild);
				powalk(x->rchild);
				printf x->key;
			}					

举例子:
图1
先序:5,3,2,4,6,7
中序:2,3,4,5,6,7
后序:2,4,3,7,6,5

2.查找(search):
需输入一个指向树根的指针x,一个关键字k。
关键字存在,返回一个指向k的结点的指针,否则返回NULL;
具体搜索过程;
(1)从树根开始查找,沿着树的一条路径。
(2)若为空树,则树中没有关键字k,返回NULL;
(3)若不是空树;
	(i)关键字k小于结点x,则在结点x的左子树进行查找;
	(ii)关键字k大于结点x,则在结点x的右子树进行查找;
	(iii)关键字k等于结点x,查找结束,返回指向结点x的指针。
	(iiii)若查找到结束也没有k,则返回NULL。
	
递归查找:
由具体搜索过程:
伪代码:
search(x,k)
if(x->key==k || x==NULL)
{
	return x;
}
if(x->key<k) return search(x->lchild,k);
else return search(x->rchild,k);


3.最小关键字:(minimum)
就是求树中最小值,因为二叉查找树可知左子树是小于右子树的,
所以一直沿着左子树进行查找直到遇到NULL,
就可以找到最小关键字。
以下是伪代码:
tree_minimum(x)
{
	while(x->key !=NULL)
	{
		x=x->lchild;
	}
}

4.最大关键字(maximum)
同理,就是一直沿着右子树进行查找直到遇到NULL;
伪代码:
tree_maximum()
{
		while(x->key!=NULL)
		{
			x=x->rchild;
		}
}

5.后继(successor),前驱(predecessor)
	后继就是在中序遍历后,相对当前点x的后一个位置;
	前驱就是在中序遍历后,相对当前点x的前一个位置;
	查询后继,有如下分类:
	(1)x的右子树非空:则后继为右子树的最小关键字;
	(2)x的右子树为空:
		(i)x为父节点的左孩子:后继为父节点;
		(ii)x为父节点的右孩子:后继为x的最低层祖先,最底层祖先满足其左子树为x的祖先;
	查询前驱,(与后继对称),有如下分类:
	(1)x的左子树非空:前驱为左子树的最大关键字;
	(2)x的左子树为空:
		(i)x为父节点的右孩子:前驱为父节点;
		(ii)x为父节点的左孩子:前驱为x的最低层祖先,并且最低层祖先满足其右子树为x的祖先。
后继伪代码:
successor(x)
if x->rchild!=NULL;
	return tree_minimum(x->rchild);
y=x->parent;
while(y!=NULL && x==y->rchild)
	x=y;
	y=y->parent;
return y;

前驱伪代码:
predecessor(x)
if x->lchild!=NULL;
	return tree_maximum(x->lchild);
y=x->parent;
while(y!=NULL && x==y->lchild)
	x=y;
	y=y->parent;
return y;

举个例子:如下图:
在这里插入图片描述
求后继:
对于第一个x右子树非空情况:假设要求7的后继,其右子树的最小关键字为8,故7的后继为8。
对于第二个x右子树为空的情况:
(1)要求8的后继,因为8是9的左孩子,故8的后继为父节点9。
(2)要求10的后继,我们可以看到10的祖先有7,6,13。因为祖先要满足祖先是最低层的并且其左子树为x的祖先,我们可以发现,7没有左子树pass掉,6的左子树为2不是10的祖先所以也Pass掉,最后只剩13,13的左子树为6,为10的祖先,所以10的后继为13。
求前驱:同理。

6.插入(insert)
插入要保证插入之后二叉搜索树的性质不被破坏。
插入要先从树根开始遍历,沿着树向下运动。
通过比较当前结点x的关键字与待插入z的关键字进行比较,决定是向左还是向右移动。
直到x移动到NULL时,将z输入此位置。
伪代码如下:
tree_insert(T,z)//T为根节点,z为待插入的值
{
	y=NULL;
	x=T;
	while(x!=NULL)
	{
		y=x;
		if z->key < x->key
			x=x->lchild;
		else
			x=x->rchild;
	}
	z->parent=y;
	if y==NULL;
		T=z;
	else if(z->key < y->key)
		y->lchild=z;
	else
		y->rchild=z;
}

脑袋没了,人傻了。
有什么错误和建议还请大佬一一指出(~)

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值