数据结构(二叉排序树)
Posted tianliang-2000
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构(二叉排序树)相关的知识,希望对你有一定的参考价值。
二叉排序树
插入,删除和查找的效率都比较高(创建时与二叉树相同)
二叉排序树又称为二叉排序树,若不为空树,则有以下性质:
- 若左子树不为空,则左子树上所有结点值均小于根节点的值
- 若右子树不为空,则右子树上所有结点值均小于根节点的值
- 他的左右子树也是二叉树排序树(递归)
查找:二叉树的中序遍历(从小到大)
插入:比根节点小的插入到二叉树根节点的左边,反之插入到右边
删除:
- 如果待删除的是叶子结点:直接删除即可
- 若待删除结点只有左孩子或者右孩子,则直接将子树接到双亲的位置上(代替删除结点即可)
- 带删除的结点左右子树都存在:
- 用该节点直接前驱或直接后继来替换该结点(只用数据覆盖)
- 用前驱的左子树代替前驱,用后继的右子树代替后继
- 如图可以看出要删除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(" 请输入删除结点:"); 124 scanf("%d",&val); 125 DeleteBST(&tree,val); 126 cenprintf(tree); 127 }
平衡二叉树
以上是关于数据结构(二叉排序树)的主要内容,如果未能解决你的问题,请参考以下文章