最近在学习浙江大学的数据结构,整理如下
二叉搜索树(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;
}