数据结构(二叉排序树)

二叉排序树spa

  插入,删除和查找的效率都比较高(建立时与二叉树相同)3d

二叉排序树又称为二叉排序树,若不为空树,则有如下性质:指针

  • 若左子树不为空,则左子树上全部结点值均小于根节点的值
  • 若右子树不为空,则右子树上全部结点值均小于根节点的值
  • 他的左右子树也是二叉树排序树(递归)

  查找:二叉树的中序遍历(从小到大)code

  插入:比根节点小的插入到二叉树根节点的左边,反之插入到右边blog

  删除:排序

  • 若是待删除的是叶子结点:直接删除便可
  • 若待删除结点只有左孩子或者右孩子,则直接将子树接到双亲的位置上(代替删除结点便可)
  • 带删除的结点左右子树都存在:
  1. 用该节点直接前驱或直接后继来替换该结点(只用数据覆盖)
  2. 用前驱的左子树代替前驱,用后继的右子树代替后继
  • 如图能够看出要删除105的话,能够用他的前驱或者后替代他
  • 前驱为104,须要注意的是他的前驱只有两种可能:为叶子结点或,或者只有左子树(用为若是有右子树的话那么105的前驱就是他的右子树了)
  • 后继用一样的道理能够得出,后继108:为叶子结点,或只有右子树
  • 因此删除一个结点时有两种方法:用前驱或后继的数据覆盖删除点的数据,用前驱的左子树接到前驱位置上,或用后继的右子树接到后继上
  • 请思考这里若是100没有右子树时,105的前驱就是他的左子树,这时就不是将前驱的右子树接到前驱位置上了,而是将前驱的右左子树接到前驱位置上

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <malloc.h>
  4 typedef int ElemType;
  5 
  6 typedef struct BiTNode{
  7     ElemType data;
  8     struct BiTNode *lchild;//左孩子
  9     struct BiTNode *rchild;//右孩子
 10 }BiTNode,* BiTree;
 11 
 12 int Delete(BiTree *);
 13 
 14 //递归查找二叉树T中是否存在key
 15 //指针f指向T的双亲,其初始值调用值为NULL
 16 //若查找成功,则指针p指向该数据元素结点并返回1
 17 //不然指针p指向查找路径上访问的最后一个结点,返回0
 18 int SearchBST(BiTree T,int key,BiTree f,BiTree *p){
 19     if(!T){//查找不成功
 20         *p=f;
 21         return 0;
 22     }else if(key==T->data){
 23         *p=T;
 24         return 1;
 25     }else if(key<T->data){
 26         return SearchBST(T->lchild,key,T,p);//在左子树继续查找
 27     }else{
 28         return SearchBST(T->rchild,key,T,p);//在右子树继续查找
 29     }
 30 }
 31 
 32 //当二叉排序树T中不存在关键字等于key的数据元素树
 33 //插入key并返回1,否者返回0
 34 int InsertBST(BiTree *T,ElemType key){
 35     BiTree p,s;
 36     if(!SearchBST(*T,key,NULL,&p)){
 37         s=(BiTree)malloc(sizeof(BiTNode));
 38         s->data=key;
 39         s->lchild=s->rchild=NULL;
 40         if(!p){//查找不到key
 41             *T=s;
 42         }else if(key<p->data){
 43             p->lchild=s;
 44         }else{
 45             p->rchild=s;
 46         }
 47         return 1;
 48     }else{
 49         return 0;//树中已有关键字相同的结点,不在插入
 50     }
 51 }
 52 
 53 void cenprintf(BiTree tree){
 54     if(tree){
 55         cenprintf(tree->lchild);
 56         printf("%d  ",tree->data);
 57         cenprintf(tree->rchild);
 58     }
 59 }
 60 
 61 int DeleteBST(BiTree *T,int key){
 62     if(!*T){
 63         return 0;
 64     }else{
 65         if(key==(*T)->data){
 66             return Delete(T);
 67         }else if(key<(*T)->data){
 68             return DeleteBST(&(*T)->lchild,key);
 69         }else{
 70             return DeleteBST(&(*T)->rchild,key);
 71         }
 72     }
 73 }
 74 
 75 int Delete(BiTree *p){
 76     BiTree q,s;
 77     if((*p)->rchild==NULL){
 78         q=*p;
 79         *p=(*p)->lchild;
 80         free(q);
 81     }
 82     else if((*p)->lchild==NULL){
 83         q=*p;
 84         *p=(*p)->rchild;
 85         free(q);
 86     }else{
 87         q=*p;
 88         s=(*p)->lchild;
 89 
 90         while(s->rchild){
 91             //q:始终表明是s是双亲结点
 92             //s:用于寻找删除结点左子树上最右边的结点(值最大的结点)(删除结点的前驱结点)
 93             q=s;
 94             s=s->rchild;
 95         }
 96         (*p)->data=s->data;
 97         //若是q==p:代表while语句循环体没有执行,即删除结点的前驱就是它的左孩子
 98         //若是前驱是它的左孩子,就说明他前驱没有右孩子;就要把左孩子接到原前驱位置上
 99         //否者表示前驱不为删除结点的左孩子,那么他可能有左孩子,必定没有右孩子,因此把前驱左孩子接到原前驱位置上
100         if(q != *p){
101             q->rchild=s->lchild;
102         }else{
103             q->lchild=s->lchild;
104         }
105         free(s);
106     }
107     return 1;
108 }
109 
110 void main(){
111     ElemType val;
112     BiTree tree=(BiTree)malloc(sizeof(BiTNode));
113     tree->data=5;
114     tree->lchild=tree->rchild=NULL;
115     printf("请输入插入树的值:");
116     scanf("%d",&val);
117     while(-1!=val){
118         InsertBST(&tree,val);
119         printf("请输入插入树的值:");
120         scanf("%d",&val);
121     }
122     cenprintf(tree);
123     printf("\n请输入删除结点:");
124     scanf("%d",&val);
125     DeleteBST(&tree,val);
126     cenprintf(tree);
127 }

平衡二叉树递归

   排序二叉树生成的二叉树结构与输入的顺序有很是重要的关系,若按循序输入的话就会生成斜二叉树,那么斜二叉树的效率是很是低的,正是有图这个缘由就出现了平衡二叉树;it

  • 平衡二叉树要求:颗树的左子树与右子树的高度最多相差1
  • BF值:树的左子树高度减右子树高度

  1 #define TRUE 1
  2 #define FALSE 0
  3 #define LH 1//左子树高
  4 #define EH 0//两子树同样高
  5 #define RH -1//右子树高
  6 typedef int ElemType;
  7 
  8 typedef struct BiTNode{
  9     ElemType data;
 10     int bf;//树的BF值
 11     struct BiTNode *lchild;//左孩子
 12     struct BiTNode *rchild;//右孩子
 13 }BiTNode,* BiTree;
 14 
 15 //左旋转
 16 void L_Rotate(BiTree *T)
 17 {
 18     BiTree R = (*T)->rchild;
 19     (*T)->rchild = R->lchild;
 20     R->lchild = *T;
 21     *T = R;
 22     return;
 23 }
 24 //右旋转
 25 void R_Rotate(BiTree *T)
 26 {
 27     BiTree L = (*T)->lchild;
 28     (*T)->lchild = L->rchild;
 29     L->rchild = *T;
 30     *T = L;
 31     return;
 32 }
 33 
 34 //T 的左边高,不平衡,使其平衡,右旋转,右旋转前先检查L->bf,
 35 //若是为RH,L要先进行左旋转,使T->lchild->bf和T->bf一致
 36 void LeftBalance(BiTree* T)
 37 {
 38     BiTree L,Lr;
 39     L = (*T)->lchild;
 40     Lr = L->rchild;
 41     switch (L->bf)
 42     {
 43         case LH:
 44             L->bf = (*T)->bf =  EH;
 45             R_Rotate(T);
 46             break;
 47         case RH:
 48             switch (Lr->bf)
 49             {
 50                 case LH:
 51                     L->bf = EH;
 52                     (*T)->bf = RH;
 53                     break;
 54                 case EH:
 55                     L->bf = (*T)->bf = EH;
 56                     break;
 57                 case RH:
 58                     L->bf = LH;
 59                     (*T)->bf = EH;
 60                     break;
 61             }
 62             Lr->bf = EH;
 63             L_Rotate(&L);
 64             R_Rotate(T);
 65             break;
 66     }
 67 }
 68 //T 的右边高,不平衡,使其平衡,左旋转,左旋转前先检查R->bf,
 69 //若是为LH,R要先进行右旋转,使T->rchild->bf和T->bf一致
 70 void RightBalance(BiTree* T)
 71 {
 72     BiTree R,Rl;
 73     R = (*T)->rchild;
 74     Rl = R->lchild;
 75     switch(R->bf)
 76     {
 77         case RH:
 78             R->bf = (*T)->bf = EH;
 79             L_Rotate(T);
 80             break;
 81         case LH:
 82             switch(R->bf)
 83             {
 84                 case LH:
 85                     R->bf = RH;
 86                     (*T)->bf = EH;
 87                     break;
 88                 case EH:
 89                     R->bf = (*T)->bf = EH;
 90                     break;
 91                 case RH:
 92                     R->bf = EH;
 93                     (*T)->bf = LH;
 94                     break;
 95             }
 96             Rl->bf = EH;
 97             R_Rotate(&R);
 98             L_Rotate(T);
 99             break;
100     }
101 }
102 
103 //taller:标志树有没有长高,长高返回TRUE,否者FALSE
104 int InsertAVL(BiTree *T,ElemType e,int *taller){
105     if(!(*T)){
106         *T=(BiTree)malloc(sizeof(BiTNode));
107         (*T)->bf=EH;
108         (*T)->data=e;
109         (*T)->lchild=(*T)->rchild=NULL;
110         *taller=TRUE;
111     }
112     else{
113         if(e==(*T)->data){
114             *taller=FALSE;
115             return FALSE;
116         }
117         if(e<(*T)->data){
118             //递归向左子树寻找:
119             //寻找到时返回FALSE:这里进入判断继续FALSE返回(一步步退出递归)
120             if(!InsertAVL(&(*T)->lchild,e,taller)){
121                 return FALSE;
122             }
123             if(*taller){
124                 //树长高了,分析树是否还平衡,并处理不平衡状况
125                 switch((*T)->bf){
126                     case LH:
127                         //在左子树高的状况下,左子树又长高了致使的不平衡
128                         LeftBalance(T);//通过处理后,长高的一层被平衡到原倒数层(左旋转/右旋转)
129                         *taller=FALSE;
130                         break;
131                     case EH:
132                         //在平衡的状况,左子树长高了
133                         (*T)->bf=LH;
134                         *taller=TRUE;
135                         break;
136                     case RH:
137                         //右子树高的状况下,左子树长高了
138                         (*T)->bf=EH;//两子树高度相等
139                         *taller=FALSE;
140                         break;
141                 }
142             }
143         }
144         else{
145             //递归向右子树寻找:
146             //寻找到时返回FALSE:这里进入判断继续FALSE返回(一步步退出递归)
147             if(!InsertAVL(&(*T)->rchild,e,taller)){
148                 return FALSE;
149             }
150             if(*taller){
151                 //树长高了,分析树是否还平衡,并处理不平衡状况
152                 switch((*T)->bf){
153                     case LH:
154                         //在左子树高的状况下,右子树长高了
155                         (*T)->bf=EH;//两子树如今等高
156                         *taller=FALSE;
157                         break;
158                     case EH:
159                         //在平衡的状况,右子树长高了
160                         (*T)->bf=RH;
161                         *taller=TRUE;
162                         break;
163                     case RH:
164                         //在右子树高的状况下,右子树又长高了致使的不平衡
165                         RightBalance(T);//通过处理后,长高的一层被平衡到原倒数层(左旋转/右旋转)
166                         *taller=FALSE;
167                         break;
168                 }
169             }
170         }
171     }
172 }
LeftBalance的4中状况;

RightBalance中的四种状况

相关文章
相关标签/搜索