1、第9章 内部排序第9章 内部排序9.1 (1)无序表:顺序查找不成功时,查找长度为n+1;成功时,平均查找长度为1/(n+1)*(1+2+(n+1)=(n+2)/2;两者不相同。(2)表中只有一个关键字等于给定值k的记录,无序表、有序表:顺序查找成功时,平均查找长度均为1/(n)*(1+2+n)=(n+1)/2;两者相同。(3)表中只有m个关键字等于给定值k的记录,无序表:ASL=n+1;有序表:ASL=(n+1)/2+m;两者不相同。9.3ASL=1/10(1+2*2+4*3+3*4)=2.99.119.14删除50后删除68后9.192267413053461301012345678910
2、ASL=(4*1+2*2+3+6)/8=17/89.25int Search-Seq(SSTable ST, KeyType key)/在顺序表ST中顺序查找其关键字等于key的数据元素,ST按关键字自大至小有序,/若找到,则函数值为该元素在表中的位置,否则为0 ST.elemST.length+1.key=key; for (i=1; ST.elemi.keykey; +i); if (ST.elemi.key=key)&(irchild; p=p-rchild);return p-data;/MaxvTelemType Minv(Bitree T)/返回二叉排序树T中所有结点的最小值for
3、 (p=T; p-lchild; p=p-lchild);return p-data;/MinvStatus IsBST(Bitree T) /判别T是否为二叉排序树 if (!T) return OK; else if (!T-lchild)|(T-lchild)&(IsBST(T-lchild)&(Maxv(T-lchild)data)&(!T-rchild)|(T-rchild)&(IsBST(T-rchild)&(Minv(T-rchild)T-data) return OKelse return ERROR;/IsBST9.33Status OutputGEx(Bitree T, T
4、elemType x) /从大到小输出给定二叉排序树T中所有值不小于x的数据元素 if (T) if (OutputGEx(T-rchild, x) if (T-data=x) print(T-data); if (OutputGEx(T-lchild, x) return OK; else return OK; else return OK;/OutputGEx第九章 查找 9.25 int Search_Sq(SSTable ST,int key)/在有序表上顺序查找的算法,监视哨设在高下标端ST.elemST.length+1.key=key;for(i=1;ST.elemi.keyke
5、y;i+);if(iST.length|ST.elemi.keyhigh) return 0; /查找不到时返回0mid=(low+high)/2;if(ST.elemmid.key=key) return mid;else if(ST.elemmid.keykey)return Search_Bin_Digui(ST,key,low,mid-1);else return Search_Bin_Digui(ST,key,mid+1,high);/Search_Bin_Digui 9.27 int Locate_Bin(SSTable ST,int key)/折半查找,返回小于或等于待查元素的最
6、后一个结点号int *r;r=ST.elem;if(key=rST.length.key) return ST.length;low=1;high=ST.length;while(low=rmid.key&keyrmid+1.key) /查找结束的条件return mid;else if(keyL.idxL.blknum.maxkey) return ERROR; /超过最大元素low=1;high=L.blknum;found=0;while(low=high&!found) /折半查找记录所在块号midmid=(low+high)/2;if(keyL.idxmid-1.maxkey)fou
7、nd=1;else if(keyL.idxmid.maxkey)low=mid+1;else high=mid-1;i=L.idxmid.firstloc; /块的下界j=i+blksize-1; /块的上界temp=L.elemi-1; /保存相邻元素L.elemi-1=key; /设置监视哨for(k=j;L.elemk!=key;k-); /顺序查找L.elemi-1=temp; /恢复元素if(kdata=key) return L.t;else if(L.t-datakey)for(p=L.h,i=1;p-data!=key;p=p-next,i+);elsefor(p=L.t,i=
8、L.tpos;p-data!=key;p=p-next,i+);L.t=p; /更新t指针return p;/Search_CSList分析:由于题目中假定每次查找都是成功的,所以本算法中没有关于查找失败的处理.由微积分可得,在等概率情况下,平均查找长度约为n/3. 9.30 typedef struct DLNode *pre; int data; DLNode *next; DLNode; typedef struct DLNode *sp; int length; DSList; /供查找的双向循环链表类型 DLNode *Search_DSList(DSList &L,int key)
9、/在有序双向循环链表存储结构上的查找算法,假定每次查找都成功p=L.sp;if(p-datakey)while(p-datakey) p=p-pre;L.sp=p;else if(p-datadatanext;L.sp=p;return p;/Search_DSList分析:本题的平均查找长度与上一题相同,也是n/3. 9.31 int last=0,flag=1; int Is_BSTree(Bitree T)/判断二叉树T是否二叉排序树,是则返回1,否则返回0if(T-lchild&flag) Is_BSTree(T-lchild);if(T-datadata;if(T-rchild&fl
10、ag) Is_BSTree(T-rchild);return flag;/Is_BSTree 9.32 int last=0; void MaxLT_MinGT(BiTree T,int x)/找到二叉排序树T中小于x的最大元素和大于x的最小元素if(T-lchild) MaxLT_MinGT(T-lchild,x); /本算法仍是借助中序遍历来实现if(lastdata=x) /找到了小于x的最大元素printf(a=%dn,last);if(lastdatax) /找到了大于x的最小元素printf(b=%dn,T-data);last=T-data;if(T-rchild) MaxLT_
11、MinGT(T-rchild,x);/MaxLT_MinGT 9.33 void Print_NLT(BiTree T,int x)/从大到小输出二叉排序树T中所有不小于x的元素if(T-rchild) Print_NLT(T-rchild,x);if(T-datadata);if(T-lchild) Print_NLT(T-lchild,x); /先右后左的中序遍历/Print_NLT 9.34 void Delete_NLT(BiTree &T,int x)/删除二叉排序树T中所有不小于x元素结点,并释放空间if(T-rchild) Delete_NLT(T-rchild,x);if(T-
12、datalchild;free(q); /如果树根不小于x,则删除树根,并以左子树的根作为新的树根if(T) Delete_NLT(T,x); /继续在左子树中执行算法/Delete_NLT 9.35 void Print_Between(BiThrTree T,int a,int b)/打印输出后继线索二叉排序树T中所有大于a且小于b的元素p=T;while(!p-ltag) p=p-lchild; /找到最小元素while(p&p-datadataa) printf(%dn,p-data); /输出符合条件的元素if(p-rtag) p=p-rtag;elsep=p-rchild;whil
13、e(!p-ltag) p=p-lchild; /转到中序后继/while/Print_Between 9.36 void BSTree_Insert_Key(BiThrTree &T,int x)/在后继线索二叉排序树T中插入元素xif(T-datartag) /T没有右子树时,作为右孩子插入p=T-rchild;q=(BiThrNode*)malloc(sizeof(BiThrNode);q-data=x;T-rchild=q;T-rtag=0;q-rtag=1;q-rchild=p; /修改原线索else BSTree_Insert_Key(T-rchild,x);/T有右子树时,插入右子
14、树中/ifelse if(T-datax) /插入到左子树中if(!T-lchild) /T没有左子树时,作为左孩子插入q=(BiThrNode*)malloc(sizeof(BiThrNode);q-data=x;T-lchild=q;q-rtag=1;q-rchild=T; /修改自身的线索else BSTree_Insert_Key(T-lchild,x);/T有左子树时,插入左子树中/if/BSTree_Insert_Key 9.37 Status BSTree_Delete_key(BiThrTree &T,int x)/在后继线索二叉排序树T中删除元素xBTNode *pre,*p
15、tr,*suc;/ptr为x所在结点,pre和suc分别指向ptr的前驱和后继p=T;last=NULL; /last始终指向当前结点p的前一个(前驱)while(!p-ltag) p=p-lchild; /找到中序起始元素while(p)if(p-data=x) /找到了元素x结点pre=last;ptr=p;else if(last&last-data=x) suc=p; /找到了x的后继if(p-rtag) p=p-rtag;elsep=p-rchild;while(!p-ltag) p=p-lchild; /转到中序后继last=p;/while /借助中序遍历找到元素x及其前驱和后继
16、结点if(!ptr) return ERROR; /未找到待删结点Delete_BSTree(ptr); /删除x结点if(pre&pre-rtag)pre-rchild=suc; /修改线索return OK;/BSTree_Delete_key void Delete_BSTree(BiThrTree &T)/课本上给出的删除二叉排序树的子树T的算法,按照线索二叉树的结构作了一些改动q=T;if(!T-ltag&T-rtag) /结点无右子树,此时只需重接其左子树T=T-lchild;else if(T-ltag&!T-rtag) /结点无左子树,此时只需重接其右子树T=T-rchild;
17、else if(!T-ltag&!T-rtag) /结点既有左子树又有右子树p=T;r=T-lchild;while(!r-rtag)s=r;r=r-rchild; /找到结点的前驱r和r的双亲sT-data=r-data; /用r代替T结点if(s!=T)s-rchild=r-lchild;else s-lchild=r-lchild; /重接r的左子树到其双亲结点上q=r;/elsefree(q); /删除结点/Delete_BSTree分析:本算法采用了先求出x结点的前驱和后继,再删除x结点的办法,这样修改线索时会比较简单,直接让前驱的线索指向后继就行了.如果试图在删除x结点的同时修改线
18、索,则问题反而复杂化了. 9.38 void BSTree_Merge(BiTree &T,BiTree &S)/把二叉排序树S合并到T中if(S-lchild) BSTree_Merge(T,S-lchild);if(S-rchild) BSTree_Merge(T,S-rchild); /合并子树Insert_Key(T,S); /插入元素/BSTree_Merge void Insert_Key(Bitree &T,BTNode *S)/把树结点S插入到T的合适位置上if(S-dataT-data)if(!T-rchild) T-rchild=S;else Insert_Key(T-rc
19、hild,S);else if(S-datadata)if(!T-lchild) T-lchild=S;else Insert_Key(T-lchild,S);S-lchild=NULL; /插入的新结点必须和原来的左右子树断绝关系S-rchild=NULL; /否则会导致树结构的混乱/Insert_Key分析:这是一个与课本上不同的插入算法.在合并过程中,并不释放或新建任何结点,而是采取修改指针的方式来完成合并.这样,就必须按照后序序列把一棵树中的元素逐个连接到另一棵树上,否则将会导致树的结构的混乱. 9.39 void BSTree_Split(BiTree &T,BiTree &A,Bi
20、Tree &B,int x)/把二叉排序树T分裂为两棵二叉排序树A和B,其中A的元素全部小于等于x,B的元素全部大于xif(T-lchild) BSTree_Split(T-lchild,A,B,x);if(T-rchild) BSTree_Split(T-rchild,A,B,x); /分裂左右子树if(T-datadataT-data) /其余部分与上一题同if(!T-rchild) T-rchild=S;else Insert_Key(T-rchild,S);else if(S-datadata)if(!T-lchild) T-lchild=S;else Insert_Key(T-lch
21、ild,S);S-lchild=NULL;S-rchild=NULL;/Insert_Key 9.40 typedef struct int data; int bf; int lsize; /lsize域表示该结点的左子树的结点总数加1 BlcNode *lchild,*rchild; BlcNode,*BlcTree; /含lsize域的平衡二叉排序树类型 BTNode *Locate_BlcTree(BlcTree T,int k)/在含lsize域的平衡二叉排序树T中确定第k小的结点指针if(!T) return NULL; /k小于1或大于树结点总数if(T-lsize=k) return T; /就是这个结点else if(T-lsizek)return Locate_BlcTree(T-lchild,k); /在左子树中寻找else return Locate_BlcTre
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1