2014福建省数据简介加强

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

(1)s-w[n],n-1 //Knap(s-w[n],n-1)=true

(2)s,n-1 // Knap←Knap(s,n-1)

2、(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->lchild

27. (1)*ppos // 根结点(2)rpos=ipos (3)rpos–ipos (4)ipos (5)ppos+1

3、连通图的生成树包括图中的全部n 个顶点和足以使图连通的n-1条边,最小生成树是边上权值之和最小的生成树。故可按权值从大到小对边进行排序,然后从大到小将边删除。每删除一条当前权值最大的边后,就去测试图是否仍连通,若不再连通,则将该边恢复。若仍连通,继续向下删;直到剩n-1条边为止。

void SpnTree (AdjList g)

//用“破圈法”求解带权连通无向图的一棵最小代价生成树。

{typedef struct {int i,j,w}node; //设顶点信息就是顶点编号,权是整型数

node edge[];

scanf( "%d%d",&e,&n) ; //输入边数和顶点数。

for (i=1;i

scanf("%d%d%d" ,&edge[i].i ,&edge[i].j ,&edge[i].w);

for (i=2;i

{edge[0]=edge[i]; j=i-1;

while (edge[j].w

edge[j+1]=edge[0]; }//for

k=1; eg=e;

while (eg>=n) //破圈,直到边数e=n-1.

{if (connect(k)) //删除第k 条边若仍连通。

{edge[k].w=0; eg--; }//测试下一条边edge[k],权值置0表示该边被删除 k++; //下条边

}//while

}//算法结束。

connect()是测试图是否连通的函数,可用图的遍历实现,

4、若第n 件物品能放入背包,则问题变为能否再从n-1件物品中选出若干件放入背包(这时背包可放入物品的重量变为s-w[n])。若第n 件物品不能放入背包,则考虑从n-1件物品选若干件放入背包(这时背包可放入物品仍为s )。若最终s=0,则有一解;否则,若s0但物品数n

(1)s-w[n],n-1 //Knap(s-w[n],n-1)=true

(2)s,n-1 // Knap←Knap(s,n-1)

5、约瑟夫环问题(Josephus 问题)是指编号为1、2、„,n 的n (n>0)个人按顺时针方向围坐成一圈,现从第s 个人开始按顺时针方向报数,数到第m 个人出列,然后从出列的下一个人重新开始报数,数到第m 的人又出列,„,如此重复直到所有的人全部出列为止。现要求采用循环链表结构设计一个算法,模拟此过程。

#include

typedef int datatype;

typedef struct node

{datatype data;

struct node *next;

}listnode;

typedef listnode *linklist;

void jose(linklist head,int s,int m)

{linklist k1,pre,p;

int count=1;

pre=NULL;

k1=head; /*k1为报数的起点*/

while (count!=s) /*找初始报数起点*/

{pre=k1;

k1=k1->next;

count++;

}

while(k1->next!=k1) /*当循环链表中的结点个数大于1时*/

{ p=k1; /*从k1开始报数*/

count=1;

while (count!=m) /*连续数m 个结点*/

{ pre=p;

p=p->next;

count++;

}

pre->next=p->next; /*输出该结点,并删除该结点*/

printf("%4d",p->data);

free(p);

k1=pre->next; /*新的报数起点*/

}

printf("%4d",k1->data); /*输出最后一个结点*/

free(k1);

}

main()

{linklist head,p,r;

int n,s,m,i;

printf("n=");

scanf("%d",&n);

printf("s=");

scanf("%d",&s);

printf("m=",&m);

scanf("%d",&m);

if (n

else

{/*建表*/

head=(linklist)malloc(sizeof(listnode)); /*建第一个结点*/

head->data=n;

r=head;

for (i=n-1;i>0;i--) /*建立剩余n-1个结点*/

{ p=(linklist)malloc(sizeof(listnode));

p->data=i;

p->next=head;

head=p;

}

r->next=head; /*生成循环链表*/

jose(head,s,m); /*调用函数*/

}

}

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

#define true 1

#define false 0

typedef struct node

{datatype data; struct node *llink,*rlink;} *BTree;

void JudgeBST(BTree t,int flag)

// 判断二叉树是否是二叉排序树,本算法结束后,在调用程序中由flag 得出结论。 { if(t!=null && flag)

{ Judgebst(t->llink,flag);// 中序遍历左子树

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

else if(pre->datadata)pre=t;//前驱指针指向当前结点

else{flag=flase;} //不是完全二叉树

Judgebst (t->rlink,flag);// 中序遍历右子树

}//JudgeBST算法结束

7、连通图的生成树包括图中的全部n 个顶点和足以使图连通的n-1条边,最小生成树是边上权值之和最小的生成树。故可按权值从大到小对边进行排序,然后从大到小将边删除。每删除一条当前权值最大的边后,就去测试图是否仍连通,若不再连通,则将该边恢复。若仍连通,继续向下删;直到剩n-1条边为止。

void SpnTree (AdjList g)

//用“破圈法”求解带权连通无向图的一棵最小代价生成树。

{typedef struct {int i,j,w}node; //设顶点信息就是顶点编号,权是整型数

node edge[];

scanf( "%d%d",&e,&n) ; //输入边数和顶点数。

for (i=1;i

scanf("%d%d%d" ,&edge[i].i ,&edge[i].j ,&edge[i].w);

for (i=2;i

{edge[0]=edge[i]; j=i-1;

while (edge[j].w

edge[j+1]=edge[0]; }//for

k=1; eg=e;

while (eg>=n) //破圈,直到边数e=n-1.

{if (connect(k)) //删除第k 条边若仍连通。

{edge[k].w=0; eg--; }//测试下一条边edge[k],权值置0表示该边被删除 k++; //下条边

}//while

}//算法结束。

connect()是测试图是否连通的函数,可用图的遍历实现,

8、已知有向图G=(V,E),其中V={V1,V2,V3,V4,V5,V6,V7},E={,,,,,,,,} 写出G 的拓扑排序的结果。

G 拓扑排序的结果是:V1、V2、V4、V3、V5、V6、V7

9、4、 void LinkList_reverse(Linklist &L)

//链表的就地逆置; 为简化算法, 假设表长大于2

{

p=L->next;q=p->next;s=q->next;p->next=NULL;

while(s->next)

{

q->next=p;p=q;

q=s;s=s->next; //把L 的元素逐个插入新表表头

}

q->next=p;s->next=q;L->next=s;

}//LinkList_reverse

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

void Translation(float *matrix,int n)

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

float sum,min ; //sum暂存各行元素之和

float *p, *pi, *pk;

for(i=0; i

{sum=0.0; pk=matrix+i*n; //pk指向矩阵各行第1个元素.

for (j=0; j

*(p+i)=sum; //将一行元素之和存入一维数组.

}//for i

for(i=0; i

{min=*(p+i); k=i; //初始设第i 行元素之和最小.

for(j=i+1;j

pi=matrix+n*i; //pi指向第i 行第1个元素.

for(j=0;j

{sum=*(pk+j); *(pk+j)=*(pi+j); *(pi+j)=sum;}

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

}//if

}//for i

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

}// Translation

[算法分析] 算法中使用选择法排序, 比较次数较多, 但数据交换(移动) 较少. 若用其它排序方法, 虽可减少比较次数, 但数据移动会增多. 算法时间复杂度为O(n2).

11、假设以邻接矩阵作为图的存储结构,编写算法判别在给定的有向图中是否存在一个简单有向回路,若存在,则以顶点序列的方式输出该回路(找到一条即可)。(注:图中不存在顶点到自己的弧)

有向图判断回路要比无向图复杂。利用深度优先遍历,将顶点分成三类:未访问;已访问但其邻接点未访问完; 已访问且其邻接点已访问完。下面用0,1,2表示这三种状态。前面已提到,若dfs (v )结束前出现顶点u 到v 的回边,则图中必有包含顶点v 和u 的回路。对应程序中v 的状态为1,而u 是正访问的顶点,若我们找出u 的下一邻接点的状态为1,就可以输出回路了。

void Print(int v,int start ) //输出从顶点start 开始的回路。

{for(i=1;i

if(g[v][i]!=0 && visited[i]==1 ) //若存在边(v,i ),且顶点i 的状态为1。 {printf(“%d”,v);

if(i==start) printf(“\n”); else Print(i,start);break;}//if

}//Print

void dfs(int v)

{visited[v]=1;

for(j=1;j

if (g[v][j]!=0) //存在边(v,j)

if (visited[j]!=1) {if (!visited[j]) dfs(j); }//if

else {cycle=1; Print(j,j);}

visited[v]=2;

}//dfs

void find_cycle() //判断是否有回路,有则输出邻接矩阵。visited 数组为全局变量。 {for (i=1;i

for (i=1;i

}//find_cycle

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

13、约瑟夫环问题(Josephus 问题)是指编号为1、2、„,n 的n (n>0)个人按顺时针方向围坐成一圈,现从第s 个人开始按顺时针方向报数,数到第m 个人出列,然后从出列的下一个人重新开始报数,数到第m 的人又出列,„,如此重复直到所有的人全部出列为止。现要求采用循环链表结构设计一个算法,模拟此过程。

#include

typedef int datatype;

typedef struct node

{datatype data;

struct node *next;

}listnode;

typedef listnode *linklist;

void jose(linklist head,int s,int m)

{linklist k1,pre,p;

int count=1;

pre=NULL;

k1=head; /*k1为报数的起点*/

while (count!=s) /*找初始报数起点*/

{pre=k1;

k1=k1->next;

count++;

}

while(k1->next!=k1) /*当循环链表中的结点个数大于1时*/

{ p=k1; /*从k1开始报数*/

count=1;

while (count!=m) /*连续数m 个结点*/

{ pre=p;

p=p->next;

count++;

}

pre->next=p->next; /*输出该结点,并删除该结点*/

printf("%4d",p->data);

free(p);

k1=pre->next; /*新的报数起点*/

}

printf("%4d",k1->data); /*输出最后一个结点*/

free(k1);

}

main()

{linklist head,p,r;

int n,s,m,i;

printf("n=");

scanf("%d",&n);

printf("s=");

scanf("%d",&s);

printf("m=",&m);

scanf("%d",&m);

if (n

else

{/*建表*/

head=(linklist)malloc(sizeof(listnode)); /*建第一个结点*/

head->data=n;

r=head;

for (i=n-1;i>0;i--) /*建立剩余n-1个结点*/

{ p=(linklist)malloc(sizeof(listnode));

p->data=i;

p->next=head;

head=p;

}

r->next=head; /*生成循环链表*/

jose(head,s,m); /*调用函数*/

}

}

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

void Hospital(AdjMatrix w,int n)

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

{for (k=1;k

for (i=1;i

for (j=1;j

if (w[i][k]+w[k][j]

m=MAXINT; //设定m 为机器内最大整数。

for (i=1;i

{s=0;

for (j=1;js) s=w[i][j];

if (s

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

}//for

}//算法结束

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

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

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

void PreToPost(ElemType pre[] ,post[],int l1,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 为空。

LinkedList head,pre=null; //全局变量

LinkedList InOrder(BiTree bt)

//中序遍历二叉树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)

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

(1)s-w[n],n-1 //Knap(s-w[n],n-1)=true

(2)s,n-1 // Knap←Knap(s,n-1)

2、(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->lchild

27. (1)*ppos // 根结点(2)rpos=ipos (3)rpos–ipos (4)ipos (5)ppos+1

3、连通图的生成树包括图中的全部n 个顶点和足以使图连通的n-1条边,最小生成树是边上权值之和最小的生成树。故可按权值从大到小对边进行排序,然后从大到小将边删除。每删除一条当前权值最大的边后,就去测试图是否仍连通,若不再连通,则将该边恢复。若仍连通,继续向下删;直到剩n-1条边为止。

void SpnTree (AdjList g)

//用“破圈法”求解带权连通无向图的一棵最小代价生成树。

{typedef struct {int i,j,w}node; //设顶点信息就是顶点编号,权是整型数

node edge[];

scanf( "%d%d",&e,&n) ; //输入边数和顶点数。

for (i=1;i

scanf("%d%d%d" ,&edge[i].i ,&edge[i].j ,&edge[i].w);

for (i=2;i

{edge[0]=edge[i]; j=i-1;

while (edge[j].w

edge[j+1]=edge[0]; }//for

k=1; eg=e;

while (eg>=n) //破圈,直到边数e=n-1.

{if (connect(k)) //删除第k 条边若仍连通。

{edge[k].w=0; eg--; }//测试下一条边edge[k],权值置0表示该边被删除 k++; //下条边

}//while

}//算法结束。

connect()是测试图是否连通的函数,可用图的遍历实现,

4、若第n 件物品能放入背包,则问题变为能否再从n-1件物品中选出若干件放入背包(这时背包可放入物品的重量变为s-w[n])。若第n 件物品不能放入背包,则考虑从n-1件物品选若干件放入背包(这时背包可放入物品仍为s )。若最终s=0,则有一解;否则,若s0但物品数n

(1)s-w[n],n-1 //Knap(s-w[n],n-1)=true

(2)s,n-1 // Knap←Knap(s,n-1)

5、约瑟夫环问题(Josephus 问题)是指编号为1、2、„,n 的n (n>0)个人按顺时针方向围坐成一圈,现从第s 个人开始按顺时针方向报数,数到第m 个人出列,然后从出列的下一个人重新开始报数,数到第m 的人又出列,„,如此重复直到所有的人全部出列为止。现要求采用循环链表结构设计一个算法,模拟此过程。

#include

typedef int datatype;

typedef struct node

{datatype data;

struct node *next;

}listnode;

typedef listnode *linklist;

void jose(linklist head,int s,int m)

{linklist k1,pre,p;

int count=1;

pre=NULL;

k1=head; /*k1为报数的起点*/

while (count!=s) /*找初始报数起点*/

{pre=k1;

k1=k1->next;

count++;

}

while(k1->next!=k1) /*当循环链表中的结点个数大于1时*/

{ p=k1; /*从k1开始报数*/

count=1;

while (count!=m) /*连续数m 个结点*/

{ pre=p;

p=p->next;

count++;

}

pre->next=p->next; /*输出该结点,并删除该结点*/

printf("%4d",p->data);

free(p);

k1=pre->next; /*新的报数起点*/

}

printf("%4d",k1->data); /*输出最后一个结点*/

free(k1);

}

main()

{linklist head,p,r;

int n,s,m,i;

printf("n=");

scanf("%d",&n);

printf("s=");

scanf("%d",&s);

printf("m=",&m);

scanf("%d",&m);

if (n

else

{/*建表*/

head=(linklist)malloc(sizeof(listnode)); /*建第一个结点*/

head->data=n;

r=head;

for (i=n-1;i>0;i--) /*建立剩余n-1个结点*/

{ p=(linklist)malloc(sizeof(listnode));

p->data=i;

p->next=head;

head=p;

}

r->next=head; /*生成循环链表*/

jose(head,s,m); /*调用函数*/

}

}

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

#define true 1

#define false 0

typedef struct node

{datatype data; struct node *llink,*rlink;} *BTree;

void JudgeBST(BTree t,int flag)

// 判断二叉树是否是二叉排序树,本算法结束后,在调用程序中由flag 得出结论。 { if(t!=null && flag)

{ Judgebst(t->llink,flag);// 中序遍历左子树

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

else if(pre->datadata)pre=t;//前驱指针指向当前结点

else{flag=flase;} //不是完全二叉树

Judgebst (t->rlink,flag);// 中序遍历右子树

}//JudgeBST算法结束

7、连通图的生成树包括图中的全部n 个顶点和足以使图连通的n-1条边,最小生成树是边上权值之和最小的生成树。故可按权值从大到小对边进行排序,然后从大到小将边删除。每删除一条当前权值最大的边后,就去测试图是否仍连通,若不再连通,则将该边恢复。若仍连通,继续向下删;直到剩n-1条边为止。

void SpnTree (AdjList g)

//用“破圈法”求解带权连通无向图的一棵最小代价生成树。

{typedef struct {int i,j,w}node; //设顶点信息就是顶点编号,权是整型数

node edge[];

scanf( "%d%d",&e,&n) ; //输入边数和顶点数。

for (i=1;i

scanf("%d%d%d" ,&edge[i].i ,&edge[i].j ,&edge[i].w);

for (i=2;i

{edge[0]=edge[i]; j=i-1;

while (edge[j].w

edge[j+1]=edge[0]; }//for

k=1; eg=e;

while (eg>=n) //破圈,直到边数e=n-1.

{if (connect(k)) //删除第k 条边若仍连通。

{edge[k].w=0; eg--; }//测试下一条边edge[k],权值置0表示该边被删除 k++; //下条边

}//while

}//算法结束。

connect()是测试图是否连通的函数,可用图的遍历实现,

8、已知有向图G=(V,E),其中V={V1,V2,V3,V4,V5,V6,V7},E={,,,,,,,,} 写出G 的拓扑排序的结果。

G 拓扑排序的结果是:V1、V2、V4、V3、V5、V6、V7

9、4、 void LinkList_reverse(Linklist &L)

//链表的就地逆置; 为简化算法, 假设表长大于2

{

p=L->next;q=p->next;s=q->next;p->next=NULL;

while(s->next)

{

q->next=p;p=q;

q=s;s=s->next; //把L 的元素逐个插入新表表头

}

q->next=p;s->next=q;L->next=s;

}//LinkList_reverse

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

void Translation(float *matrix,int n)

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

float sum,min ; //sum暂存各行元素之和

float *p, *pi, *pk;

for(i=0; i

{sum=0.0; pk=matrix+i*n; //pk指向矩阵各行第1个元素.

for (j=0; j

*(p+i)=sum; //将一行元素之和存入一维数组.

}//for i

for(i=0; i

{min=*(p+i); k=i; //初始设第i 行元素之和最小.

for(j=i+1;j

pi=matrix+n*i; //pi指向第i 行第1个元素.

for(j=0;j

{sum=*(pk+j); *(pk+j)=*(pi+j); *(pi+j)=sum;}

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

}//if

}//for i

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

}// Translation

[算法分析] 算法中使用选择法排序, 比较次数较多, 但数据交换(移动) 较少. 若用其它排序方法, 虽可减少比较次数, 但数据移动会增多. 算法时间复杂度为O(n2).

11、假设以邻接矩阵作为图的存储结构,编写算法判别在给定的有向图中是否存在一个简单有向回路,若存在,则以顶点序列的方式输出该回路(找到一条即可)。(注:图中不存在顶点到自己的弧)

有向图判断回路要比无向图复杂。利用深度优先遍历,将顶点分成三类:未访问;已访问但其邻接点未访问完; 已访问且其邻接点已访问完。下面用0,1,2表示这三种状态。前面已提到,若dfs (v )结束前出现顶点u 到v 的回边,则图中必有包含顶点v 和u 的回路。对应程序中v 的状态为1,而u 是正访问的顶点,若我们找出u 的下一邻接点的状态为1,就可以输出回路了。

void Print(int v,int start ) //输出从顶点start 开始的回路。

{for(i=1;i

if(g[v][i]!=0 && visited[i]==1 ) //若存在边(v,i ),且顶点i 的状态为1。 {printf(“%d”,v);

if(i==start) printf(“\n”); else Print(i,start);break;}//if

}//Print

void dfs(int v)

{visited[v]=1;

for(j=1;j

if (g[v][j]!=0) //存在边(v,j)

if (visited[j]!=1) {if (!visited[j]) dfs(j); }//if

else {cycle=1; Print(j,j);}

visited[v]=2;

}//dfs

void find_cycle() //判断是否有回路,有则输出邻接矩阵。visited 数组为全局变量。 {for (i=1;i

for (i=1;i

}//find_cycle

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

13、约瑟夫环问题(Josephus 问题)是指编号为1、2、„,n 的n (n>0)个人按顺时针方向围坐成一圈,现从第s 个人开始按顺时针方向报数,数到第m 个人出列,然后从出列的下一个人重新开始报数,数到第m 的人又出列,„,如此重复直到所有的人全部出列为止。现要求采用循环链表结构设计一个算法,模拟此过程。

#include

typedef int datatype;

typedef struct node

{datatype data;

struct node *next;

}listnode;

typedef listnode *linklist;

void jose(linklist head,int s,int m)

{linklist k1,pre,p;

int count=1;

pre=NULL;

k1=head; /*k1为报数的起点*/

while (count!=s) /*找初始报数起点*/

{pre=k1;

k1=k1->next;

count++;

}

while(k1->next!=k1) /*当循环链表中的结点个数大于1时*/

{ p=k1; /*从k1开始报数*/

count=1;

while (count!=m) /*连续数m 个结点*/

{ pre=p;

p=p->next;

count++;

}

pre->next=p->next; /*输出该结点,并删除该结点*/

printf("%4d",p->data);

free(p);

k1=pre->next; /*新的报数起点*/

}

printf("%4d",k1->data); /*输出最后一个结点*/

free(k1);

}

main()

{linklist head,p,r;

int n,s,m,i;

printf("n=");

scanf("%d",&n);

printf("s=");

scanf("%d",&s);

printf("m=",&m);

scanf("%d",&m);

if (n

else

{/*建表*/

head=(linklist)malloc(sizeof(listnode)); /*建第一个结点*/

head->data=n;

r=head;

for (i=n-1;i>0;i--) /*建立剩余n-1个结点*/

{ p=(linklist)malloc(sizeof(listnode));

p->data=i;

p->next=head;

head=p;

}

r->next=head; /*生成循环链表*/

jose(head,s,m); /*调用函数*/

}

}

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

void Hospital(AdjMatrix w,int n)

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

{for (k=1;k

for (i=1;i

for (j=1;j

if (w[i][k]+w[k][j]

m=MAXINT; //设定m 为机器内最大整数。

for (i=1;i

{s=0;

for (j=1;js) s=w[i][j];

if (s

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

}//for

}//算法结束

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

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

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

void PreToPost(ElemType pre[] ,post[],int l1,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 为空。

LinkedList head,pre=null; //全局变量

LinkedList InOrder(BiTree bt)

//中序遍历二叉树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)


相关内容

  • 2015年中国建筑行业深度调研报告
  • 2014-2020年中国建筑行业深度调研与投资前景预测报告     [客服QQ]992930161 [交付方式]Email电子版/特快专递 [价 格]纸介版:7000元 电子版:7200元 纸介+电子:7500元 [文章来源] 报告目录 第一章 2013-2014年中国建筑业运行环境分析 2 ...

  • 中国机械行业市场发展前景预测报告目录
  • 中国市场调研在线 行业市场研究属于企业战略研究范畴,作为当前应用最为广泛的咨询服务,其研究成果以报告形式呈现,通常包含以下内容: 一份专业的行业研究报告,注重指导企业或投资者了解该行业整体发展态势及经济运行状况,旨在为企业或投资者提供方向性的思路和参考. 一份有价值的行业研究报告,可以完成对行业系统 ...

  • 2016-2022年中国司法鉴定市场运营态势及十三五发展前景分析报告
  • 2016-2022年中国司法鉴定市场运营 态势及十三五发展前景分析报告 中国报告网 2016-2022年中国司法鉴定市场运营态势及十三五发展前景分析报告 ∙ ∙ ∙ ∙ ∙ [报告来源]中国报告网-www.chinabaogao.com [关 键 字]市场调研 前景分析 数据统计 行业分析 [出版日 ...

  • 2017年中国港口建设现状研究及发展趋势预测(目录)
  • 2017-2023年中国港口建设行业市场分析预测及投资前景评估报告(目 录) 华经情报网 www.huaon.com 公司介绍 北京艾凯德特咨询有限公司是一家专业的调研报告.行业咨询有限责任公司,公司致力于打造中国最大.最专业的调研报告.行业咨询企业.拥有庞大的服务网点,公司高覆盖.高效率的服务获得 ...

  • 2017年中国叉车行业发展前景预测
  • ▄ 前言 行业研究是通过深入研究某一行业发展动态.规模结构.竞争格局以及综合经济信息等,为企业自身发展或行业投资者等相关客户提供重要的参考依据. 企业通常通过自身的营销网络了解到所在行业的微观市场,但微观市场中的假象经常误导管理者对行业发展全局的判断和把握.一个全面竞争的时代,不但要了解自己现状,还 ...

  • 飞扬项目推介书0612
  • 深圳中星飞扬股权投资基金 募集说明书 2012年 5月 深圳市中星基金管理有限公司 中星基金 诚信服务·专业投资 1 /33 声明 本次募集说明书并非广告宣传,所有内容只是对其业务和管理公司的情 况介绍. 本募集说明书的解释权归发起人所有,发起人有权在本基金目的范围内 进行合理解释. 投资者必 ...

  • 兴业银行综合分析论文2015
  • 财务综合分析报告 组别: 组员: 专业班级: 指导老师: 目录 一. 摘要 ........................................................................ 2 二. 公司简介 ............................. ...

  • 中国冷链物流行业发展现状分析及前景预测报告
  • 前 言 冷链物流指冷藏冷冻品在生产.贮藏运输.销售,到消费前的各个环节中始终处于低温环境下,以保证产品质量,减少物品损耗的系统工程.冷链物流具有复杂性.协调性及高成本性特征,适用于果蔬.禽蛋.水产品.速冻食品.乳制品.花卉.药品等领域. 进入21世纪以来,中国冷链物流行业飞速发展,到2005年底基本 ...

  • 三明农商银行2014年度报告
  • 福建三明农村商业银行股份有限公司 2014年度报告 2015年3月30日 目 录 第一章 重 要 提 示 ............................................................................ - 3 - 第二章 释义及重要提示 .. ...