您好,欢迎来到爱go旅游网。
搜索
您的当前位置:首页年江苏省数据总结深入

年江苏省数据总结深入

来源:爱go旅游网
年江苏省数据总结深入

1、对一般二叉树,仅根据一个先序、中序、后序遍历,

不能确定另一个遍历序列。但对于满二叉树,任一结点的左右子树均含有数量相等的结点,根据此性质,可将任一遍历序列转为另一遍历序列(即任一遍历序列均可确定一棵二叉树)。

voidPreToPost(ElemTypepre[],post[],intl1,h1,l2,h2)

//将满二叉树的先序序列转为后序序列,l1,h1,l2,h2是序列初始和最后结点的下标。

{if(h1>=l1){post[h2]=pre[l1];//根结点half=(h1-l1)/2;//左或右子树的结点数

PreToPost(pre,post,l1+1,l1+half,l2,l2+half-1)//将左子树先序序列转为后序序列PreToPost(pre,post,l1+half+1,h1,l2+half,h2-1)//将右子树先序序列转为后序序列}}//PreToPost

32..叶子结点只有在遍历中才能知道,这里使用中序递归遍历。设置前驱结点指针pre,初始为空。第一个叶子结点由指针head指向,遍历到叶子结点时,就将它前驱的rchild指针指向它,最后叶子结点的rchild为空。LinkedListhead,pre=null;//全局变量LinkedListInOrder(BiTreebt)

//中序遍历二叉树bt,将叶子结点从左到右链成一个单链表,表头指针为head{if(bt){InOrder(bt->lchild);//中序遍历左子树

if(bt->lchild==null&&bt->rchild==null)//叶子结点if(pre==null){head=bt;pre=bt;}//处理第一个叶子结点else{pre->rchild=bt;pre=bt;}//将叶子结点链入链表InOrder(bt->rchild);//中序遍历左子树pre->rchild=null;//设置链表尾}

return(head);}//InOrder

时间复杂度为O(n),辅助变量使用head和pre,栈空间复杂度O(n)

2、在有向图G中,如果r到G中的每个结点都有路径可达,则称结点r为G的根结点。编写一个算法完成下列功能:(1).建立有向图G的邻接表存储结构;(2).判断有向图G是否有根,若有,则打印出所有根结点的值。3、设T是一棵满二叉树,编写一个将T的先序遍历序列转换为后序遍历序列的递归算法。4、本题应使用深度优先遍历,从主调函数进入dfs(v)时,开始记数,若退出dfs()前,已访问完有向图的全部顶点(设为n个),则有向图有根,v为根结点。将n个顶点从1到n编号,各调用一次dfs()过程,就可以求出全部的根结点。题中有

向图的邻接表存储结构、记顶点个数的变量、以及访问标记数组等均设计为全局变量。建立有向图g的邻接表存储结构参见上面第2题,这里只给出判断有向图是否有根的算法。

intnum=0,visited[]=0//num记访问顶点个数,访问数组visited初始化。constn=用户定义的顶点数;AdjListg;//用邻接表作存储结构的有向图g。voiddfs(v)

{visited[v]=1;num++;//访问的顶点数+1if(nu

m==n){printf(“%d是有向图的根。\\n”,v);num=0;}//if

p=g[v].firstarc;while(p)

{if(visied[p->adjvex]==0)dfs(p->adjvex);p=p->next;}//while

visited[v]=0;num--;//恢复顶点v}//dfs

voidJudgeRoot()

//判断有向图是否有根,有根则输出之。{staticinti;

for(i=1;i<=n;i++)//从每个顶点出发,调用dfs()各一次。{num=0;visited[1..n]=0;dfs(i);}}//JudgeRoot

算法中打印根时,输出顶点在邻接表中的序号(下标),若要输出顶点信息,可使用g[i].vertex。

5、题目中要求矩阵两行元素的平均值按递增顺序排序,由于每行元素个数相等,按平均值排列与按每行元素之和排列是一个意思。所以应先求出各行元素之和,放入一维数组中,然后选择一种排序方法,对该数组进行排序,注意在排序时若有元素移动,则与之相应的行中各元素也必须做相应变动。voidTranslation(float*matrix,intn)

//本算法对n×n的矩阵matrix,通过行变换,使其各行元素的平均值按递增排列。

{inti,j,k,l;

floatsum,min;//sum暂存各行元素之和float*p,*pi,*pk;for(i=0;i<n;i++)

{sum=0.0;pk=matrix+i*n;//pk指向矩阵各行第1个元素.for(j=0;j<n;j++){sum+=*(pk);pk++;}//求一行元素之和.*(p+i)=sum;//将一行元素之和存入一维数组.

}//fori

for(i=0;i<n-1;i++)//用选择法对数组p进行排序{min=*(p+i);k=i;//初始设第i行元素之和最小.

for(j=i+1;j<n;j++)if(p[j]<min){k=j;min=p[j];}//记新的最小值及行号.if(i!=k)//若最小行不是当前行,要进行交换(行元素及行元素之和){pk=matrix+n*k;//pk指向第k行第1个元素.pi=matrix+n*i;//pi指向第i行第1个元素.for(j=0;j<n;j++)//交换两行中对应元素.{sum=*(pk+j);*(pk+j)=*(pi+j);*(pi+j)=sum;}

sum=p[i];p[i]=p[k];p[k]=sum;//交换一维数组中元素之和.}//if}//fori

free(p);//释放p数组.}//Translation

[算法分析]算法中使用选择法排序,比较次数较多,但数据交换(移动)较少.若用其它排序方法,虽可减少比较次数,但数据移动会增多.算法时间复杂度为O(n2).6、冒泡排序算法是把大的元素向上移(气泡的上浮),也可以把小的元素向下移(气泡的下沉)请给出上浮和下沉过程交替的冒泡排序算法。

48.有n个记录存储在带头结点的双向链表中,现用双向起泡排序法对其按上升序进行排序,请写出这种排序的算法。(注:双向起泡排序即相邻两趟排序向相反方向起泡)

7、设一棵二叉树的结点结构为(LLINK,INFO,RLINK),ROOT为指向该二叉树根结点的指针,p和q分别为指向该二叉树中任意两个结点的指针,试编写一算法ANCESTOR(ROOT,p,q,r),该算法找到p和q的最近共同祖先结点r。8

、本题应使用深度优先遍历,从主调函数进入dfs(v)时,

开始记数,若退出dfs()前,已访问完有向图的全部顶点(设为n个),则有向图有根,v为根结点。将n个顶点从1到n编号,各调用一次dfs()过程,就可以求出全部的根结点。题中有向图的邻接表存储结构、记顶点个数的变量、以及访问标记数组等均设计为全局变量。建立有向图g的邻接表存储结构参见上面第2题,这里只给出判断有向图是否有根的算法。

intnum=0,visited[]=0//num记访问顶点个数,访问数组visited初始化。constn=用户定义的顶点数;AdjListg;//用邻接表作存储结构的有向图g。voiddfs(v)

{visited[v]=1;num++;//访问的顶点数+1

if(num==n){printf(“%d是有向图的根。\\n”,v);num=0;}//ifp=g[v].firstarc;while(p)

{if(visied[p->adjvex]==0)dfs(p->adjvex);p=p->next;}//while

visited[v]=0;num--;//恢复顶点v}//dfs

voidJudgeRoot()

//判断有向图是否有根,有根则输出之。{staticinti;

for(i=1;i<=n;i++)//从每个顶点出发,调用dfs()各一次。{num=0;visited[1..n]=0;dfs(i);}}//JudgeRoot

算法中打印根时,输出顶点在邻接表中的序号(下标),若要输出顶点信息,可使用g[i].vertex。

9、给定n个村庄之间的交通图,若村庄i和j之间有道路,则将顶点i和j用边连接,边上的Wij表示这条道路的长度,现在要从这n个村庄中选择一个村庄建一所医院,问这所医院应建在哪个村庄,才能使离医院最远的村庄到医院的路程最短?试设计一个解答上述问题的算法,并应用该算法解答如图所示的实例。20分

voidHospital(AdjMatrixw,intn)

//在以邻接带权矩阵表示的n个村庄中,求医院建在何处,使离医院最远的村庄到医院的路径最短。

{for(k=1;k<=n;k++)//求任意两顶点间的最短路径for(i=1;i<=n;i++)for(j=1;j<=n;j++)

if(w[i][k]+w[k][j]<w[i][j])w[i][j]=w[i][k]+w[k][j];m=MAXINT;//设定m为机器内最大整数。for(i=1;i<=n;i++)//求最长路径中最短的一条。{s=0;

for(j=1;j<=n;j++)//求从某村庄i(1<=i<=n)到其它村庄的最长路径。if(w[i][j]>s)s=w[i][j];

if(s<=m){m=s;k=i;}//在最长路径中,取最短的一条。m记最长路径,k记出发顶点的下标。

Printf(“医院应建在%d村庄,到医院距离为%d\\n”,i,m);}//for

}//算法结束

对以上实例模拟的过程略。各行中最大数依次是9,9,6,7,9,9。这几个最大数中最小者为6,故医院应建在第三个村庄中,离医院最远的村庄到医院的距离是6。

1、对图1所示的连通网G,请用Prim算法构造其最小生成树(每选取一条边画一个图)

10、由二叉树的前序遍历和中序遍历序列能确定唯一的一棵二叉树,下面程序的作用是实现由已知某二叉树的前序遍历和中序遍历序列,生成一棵用二叉链表表示的二叉树并打印出后序遍历序列,请写出程序所缺的语句。#defineMAX100typedefstructNode

{charinfo;structNode*llink,*rlink;}TNODE;charpred[MAX],inod[MAX];main(intargc,int**argv){TNODE*root;if(argc<3)exit0;

strcpy(pred,argv[1]);strcpy(inod,argv[2]);root=restore(pred,inod,strlen(pred));postorder(root);}

TNODE*restore(char*ppos,char*ipos,intn){TNODE*ptr;char*rpos;intk;if(n<=0)returnNULL;ptr->info=(1)_______;

for((2)_______;rpos<ipos+n;rpos++)if(*rpos==*ppos)break;k=(3)_______;

ptr->llink=restore(ppos+1,(4)_______,k);

ptr->rlink=restore((5)_______+k,rpos+1,n-1-k);returnptr;}

postorder(TNODE*ptr){if(ptr=NULL)return;

postorder(ptr->llink);postorder(ptr->rlink);printf(“%c”,ptr->info);}

11、有一种简单的排序算法,叫做计数排序(countsorting)。这种排序算法对一个待排序的表(用数组表示)进行排序,并将排序结果存放到另一个新的表中。必须注意的是,表中所有待排序的关键码互不相同,计数排序算法针对表中的每个记录,扫描待排序的表一趟,统计表中有多少个记录的关键码比该记录的关键码小,假设针对某一个记录,统计出的计数值为c,那么,这个记录在新的有序表中的合适的存放位置即为c。

(1)(3分)给出适用于计数排序的数据表定义;

(2)(7分)使用Pascal或C语言编写实现计数排序的算法;(3)(4分)对于有n个记录的表,关键码比较次数是多少?

(4)(3分)与简单选择排序相比较,这种方法是否更好?为什么?

12、二部图(bipartitegraph)G=(V,E)是一个能将其结点集V分为两不相交子集V1和V2=V-V1的无向图,使得:V1中的任何两个结点在图G中均不相邻,V2中的任何结点在图G中也均不相邻。(1).请各举一个结点个数为5的二部图和非二部图的例子。(2).请用C或PASCAL编写一个函数BIPARTITE判断一个连通无向图G是否是二部图,并分析程序的时间复杂度。设G用二维数组A来表示,大小为n*n(n为结点个数)。请在程序中加必要的注释。若有必要可直接利用堆栈或队列操作。【

13、设一棵二叉树的结点结构为(LLINK,INFO,RLINK),ROOT为指向该二叉树根结点的指针,p和q分别为指向该二叉树中任意两个结点的指针,试编写一算法ANCESTOR(ROOT,p,q,r),该算法找到p和q的最近共同祖先结点r。

14、若第n件物品能放入背包,则问题变为能否再从n-1件物品中选出若干件放入背包(这时背包可放入物品的重量变为s-w[n])。若第n件物品不能放入背包,则考虑从n-1件

物品选若干件放入背包(这时背包可放入物品仍为s)。

若最终s=0,则有一解;否则,若s<0或虽然s>0但物品数n<1,则无解。(1)s-w[n],n-1//Knap(s-w[n],n-1)=true(2)s,n-1//Knap←Knap(s,n-1)15、(1)p->rchild(2)p->lchild(3)p->lchild(4)ADDQ(Q,p->lchild)(5)ADDQ(Q,p->rchild)

25.(1)t->rchild!=null(2)t->rchild!=null(3)N0++(4)count(t->lchild)(5)count(t->rchild)26..(1)top++(2)stack[top]=p->rchild(3)top++(4)stack[top]=p->lchild27.(1)*ppos//根结点(2)rpos=ipos(3)rpos–ipos(4)ipos(5)ppos+1

16、设t是给定的一棵二叉树,下面的递归程序count(t)用于求得:二叉树t中具有非空的左,右两个儿子的结点个数N2;只有非空左儿子的个数NL;只有非空右儿子的结点个数NR和叶子结点个数N0。N2、NL、NR、N0都是全局量,且在调用count(t)之前都置为0.typedefstructnode

{intdata;structnode*lchild,*rchild;}node;intN2,NL,NR,N0;voidcount(node*t)

{if(t->lchild!=NULL)if(1)___N2++;elseNL++;elseif(2)___NR++;else(3)__;

if(t->lchild!=NULL)(4)____;if(t->rchild!=NULL)(5)____;}

26.树的先序非递归算法。voidexample(b)btree*b;

{btree*stack[20],*p;inttop;if(b!=null)

{top=1;stack[top]=b;while(top>0){p=stack[top];top--;

printf(“%d”,p->data);if(p->rchild!=null){(1)___;(2)___;}

if(p->lchild!=null)(3)___;(4)__;}}}}

17、#definemaxsize栈空间容量

voidInOutS(ints[maxsize])

//s是元素为整数的栈,本算法进行入栈和退栈操作。{inttop=0;//top为栈顶指针,定义top=0时为栈空。for(i=1;i<=n;i++)//n个整数序列作处理。{scanf(“%d”,&x);//从键盘读入整数序列。if(x!=-1)//读入的整数不等于-1时入栈。if(top==maxsize-1){printf(“栈满\\n”);exit(0);}elses[++top]=x;//x入栈。

else//读入的整数等于-1时退栈。{if(top==0){printf(“栈空\\n”);exit(0);}

elseprintf(“出栈元素是%d\\n”,s[top--]);}}

}//算法结

18、有一个带头结点的单链表,每个结点包括两个域,一个是整型域info,另一个是指向下一个结点的指针域next。假设单链表已建立,设计算法删除单链表中所有重复出现的结点,使得info域相等的结点只保留一个。#include<stdio.h>typedefchardatatype;typedefstructnode{datatypedata;structnode*next;}listnode;

typedeflistnode*linklist;

/*--------------------------------------------*/

/*删除单链表中重复的结点*//*--------------------------------------------*/linklistdeletelist(linklisthead){listnode*p,*s,*q;p=head->next;while(p){s=p;

q=p->next;while(q)

if(q->data==p->data){s->next=q->next;free(q);q=s->next;}else{s=q;/*找与P结点值相同的结点*/q=q->next;}

p=p->next;}

returnhead;}

19、在有向图G中,如果r到G中的每个结点都有路径可达,则称结点r为G的根结点。编写一个算法完成下列功能:(1).建立有向图G的邻接表存储结构;(2).判断有向图G是否有根,若有,则打印出所有根结点的值。20、两棵空二叉树或仅有根结点的二叉树相似;对非空二叉树,可判左右子树是否相似,采用递归算法。

intSimilar(BiTreep,q)//判断二叉树p和q是否相似{if(p==null&&q==null)return(1);

elseif(!p&&q||p&&!q)return(0);elsereturn(Similar(p->lchild,q->lchild)&&Similar(p->rchild,q->rchild))}//结束Similar

21、数组A和B的元素分别有序,欲将两数组合并到C数组,使C仍有序,应将A和B拷贝到C,只要注意A和B数组指针的使用,以及正确处理一数组读完数据后将另一数组余下元素复制到C中即可。voidunion(intA[],B[],C[],m,n)

//整型数组A和B各有m和n个元素,前者递增有序,后者递减有序,本算法

将A和B归并为递增有序的数组C。

{i=0;j=n-1;k=0;//i,j,k分别是数组A,B和C的下标,因用C描述,下标从0开始

while(i<m&&j>=0)

if(a[i]<b[j])c[k++]=a[i++]elsec[k++]=b[j--];while(i<m)c[k++]=a[i++];while(j>=0)c[k++]=b[j--];}算法结束

4、要求二叉树按二叉链表形式存储。15分(1)写一个建立二叉树的算法。(2)写一个判别给定的二叉树是否是完全二叉树的算法。BiTreeCreat()//建立二叉树的二叉链表形式的存储结构{ElemTypex;BiTreebt;

scanf(“%d”,&x);//本题假定结点数据域为整型if(x==0)bt=null;elseif(x>0)

{bt=(BiNode*)malloc(sizeof(BiNode));

bt->data=x;bt->lchild=creat();bt->rchild=creat();}

elseerror(“输入错误”);return(bt);}//结束BiTree

intJudgeComplete(BiTreebt)//判断二叉树是否是完全二叉树,如是,返回1,否则,返回0

{inttag=0;BiTreep=bt,Q[];//Q是队列,元素是二叉树结点指针,容量足够大if(p==null)return(1);

QueueInit(Q);QueueIn(Q,p);//初始化队列,根结点指针入队while(!QueueEmpty(Q)){p=QueueOut(Q);//出队

if(p->lchild&&!tag)QueueIn(Q,p->lchild);//左子女入队else{if(p->lchild)return0;//前边已有结点为空,本结点不空elsetag=1;//首次出现结点为空

if(p->rchild&&!tag)QueueIn(Q,p->rchild);//右子女入队elseif(p->rchild)return0;elsetag=1;}//while

return1;}//JudgeComplete

22、设T是一棵满二叉树,编写一个将T的先序遍历序列转换为后序遍历序列的递归算法。2

3、根据二叉排序树中序遍历所得结点值为增序的性质,

在遍历中将当前遍历结点与其前驱结点值比较,即可得出结论,为此设全局指针变量pre(初值为null)和全局变量flag,初值为true。若非二叉排序树,则置flag为false。#definetrue1#definefalse0

typedefstructnode

{datatypedata;structnode*llink,*rlink;}*BTree;voidJudgeBST(BTreet,intflag)

//判断二叉树是否是二叉排序树,本算法结束后,在调用程序中由flag得出结论。

{if(t!=null&&flag){Judgebst(t->llink,flag);//中序遍历左子树

if(pre==null)pre=t;//中序遍历的第一个结点不必判断

elseif(pre->data<t->data)pre=t;//前驱指针指向当前结点else{flag=flase;}//不是完全二叉树Judgebst(t->rlink,flag);//中序遍历右子树}//JudgeBST算法结束

24、对二叉树的某层上的结点进行运算,采用队列结构按层次遍历最适宜。intLeafKlevel(BiTreebt,intk)//求二叉树bt的第k(k>1)层上叶子结点个数{if(bt==null||k<1)return(0);BiTreep=bt,Q[];//Q是队列,元素是二叉树结点指针,容量足够大intfront=0,rear=1,leaf=0;//front和rear是队头和队尾指针,leaf是叶子结点数intlast=1,level=1;Q[1]=p;//last是二叉树同层最右结点的指针,level是二叉树的层数

while(front<=rear){p=Q[++front];

if(level==k&&!p->lchild&&!p->rchild)leaf++;//叶子结点

if(p->lchild)Q[++rear]=p->lchild;//左子女入队if(p->rchild)Q[++rear]=p->rchild;//右子女入队if(front==last){level++;//二叉树同层最右结点已处理,层数增1last=rear;}//last移到指向下层最右一元素if(level>k)return(leaf);//层数大于k后退出运行}//while}//结束LeafKLevel

25、请编写一个判别给定二叉树是否为二叉排序树的算法,设二叉树用llink-rlink法存储。

26、请设计一个算法,要求该算法把二叉树的叶子结点按从左到右的顺序连成一个单链表,表头指针为head。二叉树按二叉链表方式存储,链接时用叶子结点的右指针域来存放单链表指针。分析你的算法的时、空复杂度。

27、二部图(bipartitegraph)G=(V,E)是一个能将其结点集V分为两不相交子集V1和V2=V-V1的无向图,使得:V1中的任何两个结点在图G中均不相

邻,V2中的任何结点在图G中也均不相邻。(1).请各举一个结点个数为5的二部图和非二部图的例子。(2).请用C或PASCAL编写一个函数BIPARTITE判断一个连通无向图G是否是二部图,并分析程序的时间复杂度。设G用二维数组A来表示,大小为n*n(n为结点个数)。请在程序中加必要的注释。若有必要可直接利用堆栈或队列

操作。【

28、后序遍历最后访问根结点,即在递归算法中,根是压在栈底的。采用后序非递归算法,栈中存放二叉树结点的指针,当访问到某结点时,栈中所有元素均为该结点的祖先。本题要找p和q的最近共同祖先结点r,不失一般性,设p在q的左边。后序遍历必然先遍历到结点p,栈中元素均为p的祖先。将栈拷入另一辅助栈中。再继续遍历到结点q时,将栈中元素从栈顶开始逐个到辅助栈中去匹配,第一个匹配(即相等)的元素就是结点p和q的最近公共祖先。typedefstruct

{BiTreet;inttag;//tag=0表示结点的左子女已被访问,tag=1表示结点的右子女已被访问}stack;

stacks[],s1[];//栈,容量够大

BiTreeAncestor(BiTreeROOT,p,q,r)//求二叉树上结点p和q的最近的共同祖先结点r。

{top=0;bt=ROOT;

while(bt!=null||top>0)

{while(bt!=null&&bt!=p&&bt!=q)//结点入栈{s[++top].t=bt;s[top].tag=0;bt=bt->lchild;}//沿左分枝向下

if(bt==p)//不失一般性,假定p在q的左侧,遇结点p时,栈中元素均为p的祖先结点

{for(i=1;i<=top;i++)s1[i]=s[i];top1=top;}//将栈s的元素转入辅助栈s1保存if(bt==q)//找到q结点。

for(i=top;i>0;i--)//;将栈中元素的树结点到s1去匹配{pp=s[i].t;

for(j=top1;j>0;j--)

if(s1[j].t==pp){printf(“p和q的最近共同的祖先已找到”);return(pp);}}

while(top!=0&&s[top].tag==1)top--;//退栈

if(top!=0){s[top].tag=1;bt=s[top].t->rchild;}//沿右分枝向下遍历}//结束while(bt!=null||top>0)return(null);//q、p无公共祖先}//结束Ancestor

29、证明由二叉树的中序序列和后序序列,也可以唯一确定一棵二叉树。29.①试找出满足下列条件的二叉树

1)先序序列与后序序列相同2)中序序列与后序序列相同3)先序序列与中序序列相同4)中序序列与层次遍历序列相同

30、假设以I和O分别表示入栈和出栈操作。栈的初态和终态均为空,入栈和出栈的操作序列可表示为仅由I和O组成的序列,称可以操作的序列为合法序列,否则称为非法序列。(15分)

(1)A和D是合法序列,B和C是非法序列。(2)设被判定的操作序列已存入一维数组A中。intJudge(charA[])

//判断字符数组A中的输入输出序列是否是合法序列。如是,返回true,否则返回false。{i=0;//i为下标。j=k=0;//j和k分别为I和字母O的的个数。while(A[i]!=‘\\0’)//当未到字符数组尾就作。{switch(A[i])

{case‘I’:j++;break;//入栈次数增1。

case‘O’:k++;if(k>j){printf(“序列非法\\n”);exit(0);}}

i++;//不论A[i]是‘I’或‘O’,指针i均后移。}if(j!=k){printf

(“序列非法\\n”);return(false);}

else{printf(“序列合法\\n”);return(true);}}//算法结束。

31、因为后序遍历栈中保留当前结点的祖先的信息,用一变量保存栈的最高栈顶指针,每当退栈时,栈顶指针高于保存最高栈顶指针的值时,则将该栈倒入辅助栈中,辅助栈始终保存最长路径长度上的结点,直至后序遍历完毕,则辅助栈中内容即为所求。

voidLongestPath(BiTreebt)//求二叉树中的第一条最长路径长度

{BiTreep=bt,l[],s[];//l,s是栈,元素是二叉树结点指针,l中保留当前最长路径中的结点

inti,top=0,tag[],longest=0;while(p||top>0)

{while(p){s[++top]=p;tag[top]=0;p=p->Lc;}//沿左分枝向下if(tag[top]==1)//当前结点的右分枝已遍历

{if(!s[top]->Lc&&!s[top]->Rc)//只有到叶子结点时,才查看路径长度

if(top>longest){for(i=1;i<=top;i++)l[i]=s[i];longest=top;top--;}//保留当前最长路径到l栈,记住最高栈顶指针,退栈}

elseif(top>0){tag[top]=1;p=s[top].Rc;}//沿右子分枝向下

}//while(p!=null||top>0)}//结束LongestPath

32、由二叉树的前序遍历和中序遍历序列能确定唯一的一棵二叉树,下面程序的作用是实现由已知某二叉树的前序遍历和中序遍历序列,生成一棵用二叉链表表示的二叉树并打印出后序遍历序列,请写出程序所缺的语句。#defineMAX100typedefstructNode

{charinfo;structNode*llink,*rlink;}TNODE;charpred[MAX],inod[MAX];main(intargc,int**argv){TNODE*root;if(argc<3)exit0;

strcpy(pred,argv[1]);strcpy(inod,argv[2]);root=restore(pred,inod,strlen(pred));postorder(root);}

TNODE*restore(char*ppos,char*ipos,intn){TNODE*ptr;char*rpos;intk;if(n<=0)returnNULL;ptr->info=(1)_______;

for((2)_______;rpos<ipos+n;rpos++)if(*rpos==*ppos)break;k=(3)_______;

ptr->llink=restore(ppos+1,(4)_______,k);

ptr->rlink=restore((5)_______+k,rpos+1,n-1-k);returnptr;}

postorder(TNODE*ptr){if(ptr=NULL)return;

postorder(ptr->llink);postorder(ptr->rlink);printf(“%c”,ptr->info);}

33、给出折半查找的递归算法,并给出算法时间复杂度性分析。

34、本题应使用深度优先遍历,从主调函数进入dfs(v)时,开始记数,若退出dfs()前,已访问完有向图的全部顶点(设为n个),则有向图有根,v为根结点。将n个顶点从1到n编号,各调用一次dfs()过程,就可以求出全部的根结点。题中有向图的邻接表存储结构、记顶点个数的变量、以及访问标记数组等均设计为全局变量。建立有向图g的邻接表存储结构参见上面第2题,这里只给出判断有向图是否有根的算法。

intnum=0,visited[]=0//num记访问顶点个数,访问数组visited初始化。constn=用户定义的顶点数;AdjListg;

//用邻接表作存储结构的有向图g。

voiddfs(v)

{visited[v]=1;num++;//访问的顶点数+1

if(num==n){printf(“%d是有向图的根。\\n”,v);num=0;}//ifp=g[v].firstarc;while(p)

{if(visied[p->adjvex]==0)dfs(p->adjvex);p=p->next;}//while

visited[v]=0;num--;//恢复顶点v}//dfs

voidJudgeRoot()

//判断有向图是否有根,有根则输出之。{staticinti;

for(i=1;i<=n;i++)//从每个顶点出发,调用dfs()各一次。{num=0;visited[1..n]=0;dfs(i);}}//JudgeRoot

算法中打印根时,输出顶点在邻接表中的序号(下标),若要输出顶点信息,可使用g[i].vertex。

35、假设以I和O分别表示入栈和出栈操作。栈的初态和终态均为空,入栈和出栈的操作序列可表示为仅由I和O组成的序列,称可以操作的序列为合法序列,否则称为非法序列。(15分)

(1)A和D是合法序列,B和C是非法序列。(2)设被判定的操作序列已存入一维数组A中。intJudge(charA[])

//判断字符数组A中的输入输出序列是否是合法序列。如是,返回true,否则返回false。{i=0;//i为下标。j=k=0;//j和k分别为I和字母O的的个数。while(A[i]!=‘\\0’)//当未到字符数组尾就作。{switch(A[i])

{case‘I’:j++;break;//入栈次数增1。

case‘O’:k++;if(k>j){printf(“序列非法\\n”);exit(0);}}

i++;//不论A[i]是‘I’或‘O’,指针i均后移。}if(j!=k){printf(“序列非法\\n”);return(false);}else{printf(“序列合法\\n”);return(true);}}//算法结束。

36、我们可用“破圈法”求解带权连通无向图的一棵最小代价生成树。所谓“破圈法”就是“任取一圈,去掉圈上权最大的边”,反复执行这一步骤,直到没有

圈为止。请给出用“破圈法”求解给定的带权连通无向图的一棵最小代价生成树的详细算法,并用程序实现你所给出的算法。注:圈就是回路。

37、矩阵中元素按行和按列都已排序,要求查找时间复杂度为O(m+n),因此不能采用常规的二层循环的查找。可以先从右上角(i=a,j=d)元素与x比较,只有三种情况:一是A[i,j]>x,这情况下向j小的方向继续查找;二是A[i,j]<x,下步应向i大的方向查找;三是A[i,j]=x,查找成功。否则,若下标已超出范围,则查找失败。

voidsearch(datatypeA[][],inta,b,c,d,datatypex)

//n*m矩阵A,行下标从a到b,列下标从c到d,本算法查找x是否在矩阵A中.{i=a;j=d;flag=0;//flag是成功查到x的标志while(i<=b&&j>=c)if(A[i][j]==x){flag=1;break;}elseif(A[i][j]>x)j--;elsei++;

if(flag)printf(“A[%d][%d]=%d”,i,j,x);//假

定x为整型.elseprintf(“矩阵A中无%d元素”,x);}算法search结束。

[算法讨论]算法中查找x的路线从右上角开始,向下(当x>A[i,j])或向左(当x<A[i,j])。向下最多是m,向左最多是n。最佳情况是在右上角比较一次成功,最差是在左下角(A[b,c]),比较m+n次,故算法最差时间复杂度是O(m+n)。38、我们可用“破圈法”求解带权连通无向图的一棵最小代价生成树。所谓“破圈法”就是“任取一圈,去掉圈上权最大的边”,反复执行这一步骤,直到没有圈为止。请给出用“破圈法”求解给定的带权连通无向图的一棵最小代价生成树的详细算法,并用程序实现你所给出的算法。注:圈就是回路。

39、对二叉树的某层上的结点进行运算,采用队列结构按层次遍历最适宜。intLeafKlevel(BiTreebt,intk)//求二叉树bt的第k(k>1)层上叶子结点个数{if(bt==null||k<1)return(0);BiTreep=bt,Q[];//Q是队列,元素是二叉树结点指针,容量足够大intfront=0,rear=1,leaf=0;//front和rear是队头和队尾指针,leaf是叶子结点数intlast=1,level=1;Q[1]=p;//last是二叉树同层最右结点的指针,level是二叉树的层数

while(front<=rear){p=Q[++front];

if(level==k&&!p->lchild&&!p->rchild)leaf++;//叶子结点

if(p->lchild)Q[++rear]=p->lchild;//左子女入队if(p->rchild)Q[++rear]=p->rchild;//右子女入队if(front==last){level++;//二叉树同层最右结点已处理,层数增1last=rear;}//last移到指向下层最右一元素if(level>k)return(leaf);//层数大于k后退出运行

}//while}//结束LeafKLevel

40、给定n个村庄之间的交通图,若村庄i和j之间有道路,则将顶点i和j用边连接,边上的Wij表示这条道路的长度,现在要从这n个村庄中选择一个村庄建一所医院,问这所医院应建在哪个村庄,才能使离医院最远的村庄到医院的路程最短?试设计一个解答上述问题的算法,并应用该算法解答如图所示的实例。(20分)

41、证明由二叉树的中序序列和后序序列,也可以唯一确定一棵二叉树。当n=1时,只有一个根结点,由中序序列和后序序列可以确定这棵二叉树。设当n=m-1时结论成立,现证明当n=m时结论成立。

设中序序列为S1,S2,…,Sm,后序序列是P1,P2,…,Pm。因后序序列最后一个元素Pm是根,则在中序序列中可找到与Pm相等的结点(设二叉树中各结点互不相同)Si(1≤i≤m),因中序序列是由中序遍历而得,所以Si是根结点,S1,S2,…,Si-1是左子树的中序序列,而Si+1,Si+2,…,Sm是右子树的中序序列。

若i=1,则S1是根,这时二叉树的左子树为空,右子树的结点数是m-1,则{S2,S3,…,Sm}和{P1,P2,

…,Pm-1}可以唯一确定右子树,从而也确定了二叉树。

若i=m,则Sm是根,这时二叉树的右子树为空,左子树的结点数是m-1,则{S1,S2,…,Sm-1}和{P1,P2,…,Pm-1}唯一确定左子树,从而也确定了二叉树。最后,当1<i<m时,Si把中序序列分成{S1,S2,…,Si-1}和{Si+1,Si+2,…,Sm}。由于后序遍历是“左子树—右子树—根结点”,所以{P1,P2,…,Pi-1}和{Pi,Pi+1,…Pm-1}是二叉树的左子树和右子树的后序遍历序列。因而由{S1,S2,…,Si-1}和{P1,P2,…,Pi-1}

可唯一确定二叉树的左子树,由{Si+1,Si+2,…,Sm}和{Pi,Pi+1,…,Pm-1}可唯一确定二叉树的右子树。

42、根据二叉排序树中序遍历所得结点值为增序的性质,在遍历中将当前遍历结点与其前驱结点值比较,即可得出结论,为此设全局指针变量pre(初值为null)和全局变量flag,初值为true。若非二叉排序树,则置flag为false。#definetrue1#definefalse0

typedefstructnode

{datatypedata;structnode*llink,*rlink;}*BTree;voidJudgeBST(BTreet,intflag)

//判断二叉树是否是二叉排序树,本算法结束后,在调用程序中由flag得出结论。

{if(t!=null&&flag){Judgebst(t->llink,flag);//中序遍历左子树

if(pre==null)pre=t;//中序遍历的第一个结点不必判断

elseif(pre->data<t->data)pre=t;//前驱指针指向当前结点else{flag=flase;}//不是完全二叉树

Judgebst(t->rlink,flag);//中序遍历右子树}//JudgeBST算法结束

43、根据二叉排序树中序遍历所得结点值为增序的性质,在遍历中将当前遍历结点与其前驱结点值比较,即可得出结论,为此设全局指针变量pre(初值为null)和全局变量flag,初值为true。若非二叉排序树,则置flag为false。#definetrue1#definefalse0

typedefstructnode

{datatypedata;structnode*llink,*rlink;}*BTree;voidJudgeBST(BTreet,intflag)

//判断二叉树是否是二叉排序树,本算法结束后,在调用程序中由flag得出结论。

{if(t!=null&&flag){Judgebst(t->llink,flag);//中序遍历左子树

if(pre==null)pre=t;//中序遍历的第一个结点不必判断

elseif(pre->data<t->data)pre=t;//前驱指针指向当前结点else{flag=flase;}//不是完全二叉树Judgebst(t->rlink,flag);//中序遍历右子树}//JudgeBST算法结束

44、给出折半查找的递归算法,并给出算法时间复杂度性分析。45、冒泡排序算法是把大的元素向上移(气泡的上浮),也可以把小的元素向下移(气泡的下沉)请给出上浮和下沉过程交替的冒泡排序算法。

48.有n个记录存储在带头结点的双向链表中,现用双向起泡排序法对其

按上升序进行排序,请写出这种排序的算法。(注:双向

起泡排序即相邻两趟排序向相反方向起泡)

46、对一般二叉树,仅根据一个先序、中序、后序遍历,不能确定另一个遍历序列。但对于满二叉树,任一结点的左右子树均含有数量相等的结点,根据此性质,可将任一遍历序列转为另一遍历序列(即任一遍历序列均可确定一棵二叉树)。voidPreToPost(ElemTypepre[],post[],intl1,h1,l2,h2)

//将满二叉树的先序序列转为后序序列,l1,h1,l2,h2是序列初始和最后结点的下标。

{if(h1>=l1){post[h2]=pre[l1];//根结点half=(h1-l1)/2;//左或右子树的结点数

PreToPost(pre,post,l1+1,l1+half,l2,l2+half-1)//将左子树先序序列转为后序序列PreToPost(pre,post,l1+half+1,h1,l2+half,h2-1)//将右子树先序序列转为后序序列

}}//PreToPost

32..叶子结点只有在遍历中才能知道,这里使用中序递归遍历。设置前驱结点指针pre,初始为空。第一个叶子结点由指针head指向,遍历到叶子结点时,就将它前驱的rchild指针指向它,最后叶子结点的rchild为空。LinkedListhead,pre=null;//全局变量LinkedListInOrder(BiTreebt)

//中序遍历二叉树bt,将叶子结点从左到右链成一个单链表,表头指针为head{if(bt){InOrder(bt->lchild);//中序遍历左子树

if(bt->lchild==null&&bt->rchild==null)//叶子结点if(pre==null){head=bt;pre=bt;}//处理第一个叶子结点else{pre->rchild=bt;pre=bt;}//将叶子结点链入链表InOrder(bt->rchild);//中序遍历左子树pre->rchild=null;//设置链表尾}

return(head);}//InOrder

时间复杂度为O(n),辅助变量使用head和pre,栈空间复杂度O(n)

47、请编写一个判别给定二叉树是否为二叉排序树的算法,设二叉树用llink-rlink法存储。

48、因为后序遍历栈中保留当前结点的祖先的信息,用一变量保存栈的最高栈顶指针,每当退栈时,栈顶指针高于保存最高栈顶指针的值时,则将该栈倒入辅助栈中,辅助栈始终保存最长路径长度上的结点,直至后序遍历完毕,则辅助栈中内容即为所求。

voidLongestPath(BiTreebt)//求二叉树中的第一条最长路径长度

{BiTreep=bt,l[],s[];//l,s是栈,元素是二叉树结点指针,l中保留当前最长路径中的结点

inti,top=0,tag[],longest=0;while(p||top>0)

{while(p){s[++top]=p;tag[top]=0;p=p->Lc;}//沿左分枝向下if(tag[top]==1)//当前结点的右分枝已遍历

{if(!s[top]->Lc&&!s[top]->Rc)//只有到叶子结点时,才查看路径长度

if(top>longest){for(i=1;i<=top;i++)l[i]=s[i];longest=top;top--;}//保留当前最长路径到l栈,记住最高栈顶指针,退栈}

elseif(top>0){tag[top]=1;

p=s[top].Rc;}

}//while(p!=null||top>0)}//结束LongestPath

//沿右子分枝向下

49、设有两个集合A和集合B,要求设计生成集合C=A∩B的算法,其中集合A、

B和C用链式存储结构表示。

typedefstructnode{intdata;structnode*next;}lklist;voidintersection(lklist*ha,lklist*hb,lklist*&hc){

lklist*p,*q,*t;

for(p=ha,hc=0;p!=0;p=p->next)

{for(q=hb;q!=0;q=q->next)if(q->data==p->data)break;

if(q!=0){t=(lklist*)malloc(sizeof(lklist));t->data=p->data;t->next=hc;hc=t;}}}

50、若第n件物品能放入背包,则问题变为能否再从n-1件物品中选出若干件放入背包(这时背包可放入物品的重量变为s-w[n])。若第n件物品不能放入背包,则考虑从n-1件物品选若干件放入背包(这时背包可放入物品仍为s)。若最终s=0,则有一解;否则,若s<0或虽然s>0但物品数n<1,则无解。(1)s-w[n],n-1//Knap(s-w[n],n-1)=true(2)s,n-1//Knap←Knap(s,n-1)

因篇幅问题不能全部显示,请点此查看更多更全内容

Copyright © 2019- igat.cn 版权所有 赣ICP备2024042791号-1

违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务