二叉搜索树和平衡二叉树

二叉搜索树

二叉搜索树也称二叉排序树或二叉查找树
储存模式:
1,非空左子树的所有键值小于根结点键值
2,非空右子树的所有键值大于根节点键值
3,左右子树都是二叉搜索树

查找元素:

循环实现:

position find (elementtype x,binTree bts){
	while(bts){
		if(x > bts->data) bts=bts->right;
		else if(x < bts->data) bts=bts->left;
		else return bts;
	}
	return NULL;
}

递归实现:

position find (elementtype x,binTree bts){
	if(!bts)return NULL;
	if(x > bts->data) return find(x,bts->right);
	else if(x < bts->data) return find(x,bts->left);
	else return bts;
}

循环实现比递归实现效率更快。

查找最大值:一直找右结点
position finMin(binTree bts){
	if(!bts) return NULL;
	else if (!bts->left) return bts;
	else return finMin(bts->left);
}
查找最小值:一直找左结点
position finMax(binTree bts){
	if(bts)
		while(bts->right) bts=bts->bts->right;
	return bts;
}
插入元素:

插入的元素x。
如果x大于结点就比较右子树,小于就比较左子树。
如果比较后结点所指为空,x大于该结点就插到
递归实现:

binTree insert(elementtype x,binTree bts){
	if(!bts){
		//若原树为空,生成并返回一个结点的二叉搜索树
		bts=malloc(sizeof(struct treeNode));
		bts->data=x;
		bts->left=bts->right=NULL;
	}else{
		//查找插入元素的位置
		//递归插入左子树
		if(x < bts->data) bts->left=insert(x,bts->left);
		//递归插入右子树
		else if(x > bts->right) bts->right = insert(x,bts->right);
		//else x=bts->data啥也不做
		return bts;
	}
}
删除元素:
binTree delete(elementtype x,binTree bts){
	position tmp;
	if(!bts)printf("meiyou");
	else if(x < bts->data) bts->left = delete(x,bts->left);
	else if(x > bts->data) bts->right = delete(x,bts->right);
	//找到了删除的结点
	else {
		//被删除有左右两个元素
		if(bts->left && bts->right){
			//在右子树种找最小的元素填充删除
			tmp=finMin(bts->right);
			bts->data=tmp->data;
			//在删除结点的右子树中删除最小元素
			bts->right=delete(bts->data,bts->right);
		}else{
			//被删除结点有一个或无结点
			tem=bts;
			if(!bts->left){//有右孩子或无子节点
				bts = bts->right;
			}else if(!bts) bts=bts->left;//有左孩子或无子节点
			free(tmp);
		}
	}
	return bts;
}

平衡二叉树(Balanced Binary Tree)(AVL树)

平衡二叉树是搜索树/查找树,要保证左边小右边大。
平衡因子(Balance Factor,简称BF):BF(T)=h(左)-h(右)
h为树的高度。
平衡二叉树(Balanced Binary Tree):空树,或者
任一结点左右子树高度差的绝对值不超过1,即 | BF(T) | <= 1
那么n(h)是高度为h的平衡二叉树的最小结点是:如下公式。
在这里插入图片描述
给定结点数n,AVL树的最大高度为O(log₂n)。那么他的查找效率也就是O(log₂n)。

平衡二叉树的节点插入

平衡二叉树插入节点可能会破坏平衡。所以要对插入节点后的二叉树进行调整。且调整后仍要是平衡二叉树,依旧要左边小右边大。

调整主要是要考虑的是**以哪个节点为根节点的树被破坏了平衡。**也就是| BF |大于1了。
平衡二叉树所有破坏平衡的解决方法就是如下4种。

数据结构
typedef struct structnode *snode;
typedef struct structnode node;
structnode{
int val;//值
node *left;//左孩子 
node *right;//右孩子
};
求高函数
//求树的高度的函数:i
ntdepth(node *root){
	if(root==NULL) {return0; }
	int dep1=depth(root->left);
	int dep2=depth(root->right);
	return (dep1>dep2?dep1:dep2)+1;
}
RR旋转(右单旋转)

RR旋转解决的是像下图插入1元素节点问题。
1不管是插在左还是右都用的是这个方法。将2领出来作为根结点。2的旋转方向是向右。
在这里插入图片描述

C语言代码

node *RightRotate(node *root){//右旋 RR
	node *temp=root->left; 
	root->left=temp->right; 
	temp->right=root;
	return temp;
}
LL旋转

在这里插入图片描述

C语言

node *LeftRotate(node *root){//左旋	LL
	node *temp=root->right; 
	root->right=temp->left; 
	temp->left=root;
	return temp;
}
LR旋转

实例
c

//LR旋转代码如下:
node *LeftRightRotate(node *root){
	//先对root的左子树左旋再对root右旋 
	root->left=LeftRotate(root->left);
	return RightRotate(root);
}
RL旋转

实例
c

//RL旋转代码如下:
node *RightLeftRotate(node *root){
	//先对root的右子树右旋再对root左旋 
	root->right=RightRotate(root->right);
	return LeftRotate(root);
}
插入函数
//插入
node *Insert(node *root,int v){
	if(root==NULL) {
		root=(snode)malloc(sizeof(struct structnode));
		root->val=v; 
		root->left=NULL;
		root->right=NULL; 
	}else {
		if(v < root->val) {
			//插到左子树上 
			root->left=Insert(root->left,v);
			if(depth(root->left)-depth(root->right)>=2) {
				//左边高右边低
				if(v<root->left->val) {//右旋 
					root=RightRotate(root); 
				}else {//先对其左子树左旋再右旋 
					root=LeftRightRotate(root); 
				} 
			}
		}else{//插到右子树上 
			root->right=Insert(root->right,v);
			if(depth(root->right)-depth(root->left)>=2) {
				if(v>root->right->val) {//左旋 
					root=LeftRotate(root); 
				}else {//先对其右子树右旋再左旋 
					root=RightLeftRotate(root); 
				}
			}
		}
	}
	return root;
}

红黑树

红黑树(Red Black Tree):是一种自平衡二叉树。红黑树的子树也是红黑树。红黑树是AVL树的变体,他的左右子树高度差可能大于1,所以严格意义上红黑树不是AVL树。
红黑树可以在O(log n)时间内做查找,插入和删除。
特征
红黑树的每个结点都带有颜色属性,(红色或黑色)。有如下性质:

  1. 是二叉搜索树,具备二叉搜索树的性质
  2. 结点是红色或黑色
  3. 根结点和所有叶子结点是黑色。(叶子是NULL结点)
  4. 每个红色结点的两个子结点都是黑色。(从每个叶子到根的所有路径上不能有两个连续的红色结点)
  5. 从任一结点到其每个叶子的所有路径都包含相同数目的黑色结点
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值