二叉搜索树

最近在学习浙江大学的数据结构,整理如下
二叉搜索树(BST, Binary Search Tree)也称二叉排序树或二叉查找树
静态查找
一般是对于动态查找
二叉搜索树:一棵二叉树,可以为空,如果不为空,满足以下性质
1.非空左子树的所有键值小于其根节点键值
2.非空右子树的所有键值大于其根结点键值
3.左右子树都是二叉搜索树
树的实现
typedef int ElementType;
typedef struct TreeNode *BinTree;
typedef BinTree Position;
struct TreeNode{
    ElementType Data;
    BinTree Left;
    BinTree Right;
};
二叉搜索树的操作
1.Find
查找某一已知元素
Position Find(ElementType X,BinTree BST)
{
	if(!BST) return NULL;
	if(X>BST->Data) 
        return Find(X,BST->Right);
	else if(X<BST->Data)
        return Find(X,BST->Left);
	else return BST;	
};
对于这种尾递归,可以改为循环实现
Position Find(ElementType X,BinTree BST)
{
      while(BST)
      {
	    if(X>BST->Data)
              BST=BST->Right;
	    else if(X<BST->Data) 
              BST=BST->Left;
	    else return BST;
      };
      return NULL;
	
};
查找该二叉树的最大最小值
BinTree FindMin(BinTree BST)
{
	if(!BST) return NULL;
	else if(!BST->Left) return BST; 
	else  return FindMin(BST->Left);
};
同样,该查找的循环实现
BinTree FindMax(BinTree BST)
{
 if(BST)
     while(BST->Right)BST=BST->Right; 
 return BST;
};
2.Insert
元素的插入操作和元素的查找类似
BinTree Insert(ElementType X,BinTree BST)
{
	if(!BST) 
	{
	    BST=malloc(sizeof(struct TreeNode));
	    if(!BST) exit(0);
		BST->Data=X;BST->Left=BST->Right=NULL;
	}
	else if(X<BST->Data) BST->Left=Insert(X,BST->Left);//对于元素接在节点域后面要通过递归返回地址实现
	else if(X>BST->Data) BST->Right=Insert(X,BST->Right); 
	return BST;
};
3.Delete
删除树的结点:
1.如果删除的是叶结点,将其父节点指向该节点指针置为NULL
2.如果删除的是只有一个子节点的节点,将该节点的父节点指针指向要删除节点的子节点
3.如果要删除的有两个自己节点,在该节点的左子树找到最大的元素(或者在右子树中找到最小的元素),将其替换掉该节点
BinTree Delete(ElementType X,BinTree BST)
{
	Position Temp;
	if(!BST); 
	else if(X<BST->Data) BST->Left=Delete(X,BST->Left);//递归返回删除节点的子节点,接在父节点上
	else if(X<BST->Data) BST->Right=Delete(X,BST->Right); 
	else if(BST->Left&&BST->Right)//左右子树都不空
	        {
	        	Temp=FindMin(BST->Right);
	        	BST->Data=Temp->Data;
	        	BST->Right=Delete(BST->Data,BST->Right);
			}
	else    
	    {
	    	Temp=BST;
	    	if(!BST->Left)BST=BST->Right;//左子树为空,将该指针指向其右子树
	    	else if(!BST->Right)BST=BST->Left;//右子数为空,将该指针指向其左子树
	    	free(Temp);
		}
	return BST;
};
二 平衡二叉树
1.平衡二叉树
平衡因子(Balance Factor,简称BF):BF(T)=|hL-hR|。其中hL和hR分别为T的左右子树高度。
平衡二叉树(Balance Binary Tree)(AVL树):
    树可以为空,如果树不为空,则满足性质:任意节点的左右子树高度差不超过1
平衡二叉树的实现
typedef struct AVLNode *Position;
typedef Position AVLTree; /* AVL树类型 */
struct AVLNode{
 ElementType Data; 
 AVLTree Left; 
 AVLTree Right;
 int Height; /* 树高 */
};
平衡二叉树的高度:
    考虑高度为h的平衡二叉树最少需要的结点数: n(h)=n(h-1)+n(h-2)+1
    类比斐波那契数列可得树结点的递推公式:    n(h)=F(h+2)-1;
    则n个结点对应树的最小高度为logn阶
2.平衡二叉树的操作
插入
在平衡二叉树的插入新的元素时,以前小于1的平衡因子会被破坏,所以需要对平衡二叉树做相应的调整
RR旋转
当插入的元素在被破坏结点的右子树的右子树上,即RR插入,需要做RR旋转
代码实现如下:
AVLTree SingleRightRotation ( AVLTree A )
{/*注意:A必须有一个右子结点B*/
 /* 将A与B做右单旋,更新A与B的高度,返回新的根结点B*/
 AVLTree B= A->Right;
 A->Right=B->Left;
 B->Left=A;
 A->Height=Max(GetHeight(A->Left),GetHeight(A->Right))+1;
 B->Height=Max(GetHeight(B->Left),A->Height)+1;
 return B;
}

LL旋转
当插入的元素在被破坏节点的左子树的左子树上,即LL插入,需要做LL旋转
代码实现如下:
AVLTree SingleLeftRotation ( AVLTree A )
{ /* 注意:A必须有一个左子结点B */
  /* 将A与B做左单旋,更新A与B的高度,返回新的根结点B */     
 
    AVLTree B=A->Left;
    A->Left=B->Right;
    B->Right=A;
    A->Height=Max(GetHeight(A->Left),GetHeight(A->Right))+1;
    B->Height=Max(GetHeight(B->Left),A->Height)+1;
    return B;
}
LR旋转
当插入的元素在被破坏结点的左子树的右子树上,即LR插入,需要做LR旋转
实现如下:
AVLTree DoubleLeftRightRotation ( AVLTree A )
{ /* 注意:A必须有一个左子结点B,且B必须有一个右子结点C*/
  /*将A、B与C做两次单旋,返回新的根结点C*/
  /*将B与C做右单旋,C被返回*/
  A->Left=SingleRightRotation(A->Left);
  /* 将A与C做左单旋,C被返回*/
  return SingleLeftRotation(A);
}
RL旋转
当插入的元素在被破坏结点的右子树的左子树上,即RL插入,需要做RL旋转
实现如下:
AVLTree DoubleRightLeftRotation ( AVLTree A )
{ /*注意:A必须有一个右子结点B,且B必须有一个左子结点C*/
  /*将A、B与C做两次单旋,返回新的根结点C*/
  /*将B与C做左单旋,C被返回*/
  A->Right=SingleLeftRotation(A->Rigth);
  /* 将A与C做左单旋,C被返回*/
  return SingleRightRotation(A);
}
则插入操作的具体实现如下
AVLTree Insert( AVLTree T, ElementType X )
{/*将X插入AVL树T中,并且返回调整后的AVL树*/
  if(!T)
  {/*若插入空树,则新建包含一个结点的树*/
  	T=(AVLTree)malloc(sizeof(struct AVLNode));
  	T->Data=X;
  	T->Height=0;
  	T->Left=T->Right=NULL;
  }
  else if(X<T->Data)
  {
  	/*插入T的左子树*/
  	T->Left=Insert(T->Left,X);
  	/*如果需要左旋*/
  	if(GetHeight(T->Left)-GetHeight(T->Right)==2)  //判断平衡因子是否被破坏
  	if(X<T->Left->Data)
  	T=SingleLeftRotation(T);/*判断是否需要左单旋*/
  	else
  	T=DoubleLeftRightRotation(T);/*判断是否需要左-右双旋*/
  }
  else if(X>T->Data)
  {
  	/*插入T的右子树*/
  	T->Right=Insert(T->Right,X);
  	/*如果需要右旋*/
  	if(GetHeight(T->Left)-GetHeight(T->Right)==-2)
  	if(X>T->Right->Data)
  		T=SingleRightRotation(T);/*右单旋*/
  	else
 		T=DoubleRightLeftRotation(T);/*右-左双旋*/
  }
	/*else X==T->Data,无须插入*/
	/*更新树高*/
	T->Height=Max(GetHeight(T->Left),GetHeight(T->Right))+1;
	return T;
}





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值