二叉搜索树

来源:互联网 发布:阿里云大厦有什么公司 编辑:程序博客网 时间:2024/06/09 23:18
最近在学习浙江大学的数据结构,整理如下
二叉搜索树(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;}