11.现在有一个已排序的字典,请改写二分法检索算法,使之当排序码key在字典中重复出现时算法能找出第一个key出现的元素下标(用*position来保存)。保持算法时间代价为O(logn)。【答】思路一般的二分法检索算法只要找出关键码key在字典中的一个下标。在比较的过程中,一旦发现相等,记录下当前下标mid就符合要求。程序如下:数据结构字典采用6.1.4节中的顺序表示法。typedefintKeyType;typedefintDataType;二分法检索算法intbinarySearch(SeqDictionary*pdic,KeyTypekey,int*position){intlow,mid,high;low=0;high=pdic-n-1;while(low=high){mid=(low+high)/2;if(pdic-element[mid].key==key){*position=mid;returnTRUE;}elseif(pdic-element[mid].keykey)high=mid-1;elselow=mid+1;}*position=low;returnFALSE;}改写后的算法想要找出关键码key在字典中第一次出现的下标。在比较中,如果遇到相等(key与pdic-element[mid].key相等),则需要分情形讨论。(1)如果当前下标mid等于0,或者key与pdic-element[mid-1].key不等,那么mid一定是key第一次出现的下标,返回mid即可。(2)如果情形(1)不成立,那么mid一定大于等于key第一次出现的下标,需要在low和mid-1之间继续进行搜索,找出key第一次出现的下标。下面算法中,加粗的部分是对原算法的修改。修改后的二分法检索算法intbinarySearch1(SeqDictionary*pdic,KeyTypekey,int*position){/*算法结束后,*position存放key第一次出现的下标*/intlow,mid,high;low=0;high=pdic-n-1;2while(low=high){mid=(low+high)/2;if(pdic-element[mid].key==key){if(mid==0||key!=pdic-element[mid-1].key){*position=mid;returnTRUE;}/*此时mid就是key在字典中第一次出现的下标*/elsehigh=mid-1;/*在左半段继续搜索*/}elseif(pdic-element[mid].keykey)high=mid-1;elselow=mid+1;}*position=low;returnFALSE;}代价分析该算法的时间复杂度为O(logn)。2.试编写一算法求出指定结点在给定的二叉排序树中所在的层数。【答】数据结构采用7.1.3节中字典的二叉排序树表示。算法intsearch_layer(PBinTreepbtree,PBinTreeNodepnode){/*返回二叉排序树*pbtree中结点*pnode所在层数,要求所给结点在树中*/intlayer=0;PBinTreeNodep=*pbtree;while(p!=NULL){if(p-key==pnode-key)returnlayer;/*查找结点成功,返回层数*/if(p-keypnode-key){p=p-llink;/*进入左子树继续查找*/layer++;}else{p=p-rlink;/*进入右子树继续查找*/layer++;}}return-1;/*查找结点失败*/}3代价分析假设二叉排序树有n个结点,高度是h(2logn=h=n),算法执行的时间代价最坏为O(h)。注意根结点为零层。3.试编写一算法在给定的二叉排序树上找出任意两个不同结点最近的公共祖先(若在两结点A,B中,A是B的祖先,则认为A,B最近的公共祖先就是A)。数据结构同上题算法intFindLowestCommonAncestor(pBinSearchNoderoot,intvalue1,intvalue2){pBinSearchNodecurnode=root;while(1){if(curnode-keyvalue1&&curnode-keyvalue2)curnode=curnode-llink;elseif(curnode-keyvalue1&&curnode-keyvalue2)curnode=curnode-rlink;elsereturncurnode-key;}}4.设计一个有效的算法,在1000个无序的元素中,挑选出其中前5个最大的元素。【答】数据结构typedefintKeyType;typedefintDataType;typedefstruct{KeyTypekey;/*排序码字段*/DataTypeinfo;/*记录的其它字段*/}RecordNode;typedefstruct{intn;/*n为文件中的记录个数*/RecordNode*record;}SortObject;思路这里不需要整体排序,故选择一种能较快得出最终排序段的前一部分的算法改造即可,如直接选择排序,起泡排序,堆排序都能最先得出前5个最大元素。综合考虑算法的时间代价,选择直接选择排序算法改造即可。算法函数返回一个数组,数组中存着挑出的元素,为动态分配的。RecordNode*Outmax(SortObject*pvector,intout){4inti,j,k;RecordNode*outpart;RecordNodetemp;if(outpvector-n){printf(thegivenvalueiswrong!);returnNULL;}outpart=(RecordNode*)malloc(out*sizeof(RecordNode));if(outpart==NULL){printf(Nospace!\n);returnNULL;}for(i=0;iout;i++){k=i;for(j=i+1;jpvector-n;j++)if(pvector-record[j].keypvector-record[k].key)k=j;if(k!=i){temp=pvector-record[i];pvector-record[i]=pvector-record[k];pvector-record[k]=temp;}outpart[i]=pvector-record[i];}returnoutpart;}代价分析O(n*m)(设从n个元素中选出m个最大元素)。5.写一个算法来判断对给定有向图中的指定顶点是否至少存在一条有向边指向它。【答】图有三种表示方法:出边表(邻接表的一种),入边表(邻接表的一种)和邻接矩阵。相应的有三种算法。设n为顶点数,m为边数。对于出边表,顺次搜索一遍边即可,时间代价为O(m)。对于入边表,判断指定顶点的边表头指针是否非空即可,时间代价为O(1)。对于邻接矩阵,搜索矩阵中指定顶点对应的列,判断其中是否有非0元即可,时间代价为O(n)。以出边表为例,给出一个算法如下。数据结构采用9.1.3节中有向图的邻接表(出边表)表示法。5算法intis_end(GraphListg,intk){/*判断图g中是否有边指向第k个结点(0=k=g.n-1)*/EdgeListp;inti;for(i=0;ig.n;i++){p=g.vexs[i].edgelist;while(p!=NULL){if(p-endvex==i)return1;p=p-nextedge;}}return0;}代价分析该算法的时间复杂度为O(m)。6.设计一个算法,确定(无权)图中每一对结点之间的可达关系。【答】数据结构采用图的邻接矩阵表示法。#defineMAXVEX100typedefchar*VexType;typedefintAdjType;typedefstruct{VexTypevexs[MAXVEX];/*顶点信息*/AdjTypearcs[MAXVEX][MAXVEX];/*边信息*/intn;/*图的顶点个数*/}GraphMatrix;思路这里介绍Warshall算法,该算法解决了(无权)图的可达性问题。算法用到了一个矩阵a(a作为算法的参数之一)。开始时,对矩阵a中元素赋值,使a与图的邻接矩阵相等。这样,矩阵a记录的就是所有直接的边连接。算法的核心部分是一个三重循环。其中外重循环的循环次数为n,每次循环更新a中的元素。循环一次后,a中记录的就是所有直接连接或者只经由结点0而形成的通路的情况。循环k(1≤k≤n)次后,a中记录的就是所有至多只经由结点0,1,…,k1而形成的通路的情况。这样,算法结束时,矩阵a中记录的就是每一对结点之间的可达性信息。a[i][j]为1,表示从结点i到结点j是可达的;为0,则表示不可达。算法voidwarshall(GraphMatrix*pgraph,inta[][MAXVEX]){inti,j,m;for(i=0;ipgraph-n;i++)/*对矩阵a中元素赋值,使a与图的邻接矩阵相等*/for(j=0;jpgraph-n;j++)6a[i][j]=pgraph-arcs[i][j];for(m=0;mpgraph-n;m++)/*算法的核心部分,一个三重循环*/for(i=0;ipgraph-n;i++)for(j=0;jpgraph-n;j++)a[i][j]=a[i][j]||(a[i][m]&&a[m][j]);}代价分析算法的核心部分是一个三重循环,每重的循环次数为n,因此该算法的时间代价为O(n3)。调试结果该示例程序计算下图的可达性:运行结果如下:010111000111010111000000000101000000