一、选择题
- B 2.A 3.B 4.C 5.D 6.A 7.D 8.B 9.D 10.B
二、填空题
三、判断题
- × 例如,一个有向图G=(V,E),V={0,1,2,3},E={<0,1>,<1,2>,<2,3>,❤️,0>},则可以从任一顶点访问到每个顶点,但该图却非完全图
- √
- √
- × 广度优先遍历算法适合于有向图和无向图
- √ 任何一条边计入一个顶点的入度和另一个顶点的出度
- √
- × 最大出度为n
- × 一个有向图G=(V,E),V={0,1,2},E={<0,1>,<1,0>,<1,2>,<2,1>},该图的邻接矩阵是一个对称矩阵,但该有向图不是完全有向图
- × 只有减少所有关键路径中的公共活动的权值时,整个工期才可能减少
- √
四、简答题
五、计算题
1.DFS的非递归思想是:采用一个顺序栈s[]保存被访问过的节点,先将顶点v入栈,并修改其访问标志,在栈不空时循环:出栈顶点j,访问之,将其所有未访问过的邻接点入栈,并同时修改它们的访问标志。对应的算法如下:
void DFS(AGraph *G,int v)
{
int visited[MAXV];
int i,j;
int st[MAXV];
int top=-1;
ArcNode *p;
//访问标志数组置为0
for(i=0;i<G->n;i++)
visited[i]=0;
top++;
//初始顶点进栈
st[top]=v;
//修改访问标志位
visited[v]=1;
//栈不空时循环
while(top>-1)
{
//出栈
j=st[top];
top--;
printf("%d ",j);
//找第一个邻接点
p=G->adjlist[j].firstarc;
while(p)
{
//将未访问过的邻接点进栈
if(visited[p->adjvex]==0)
{
top++;
st[top]=p->adjvex;
//修改访问标志
visited[p->adjvex] = 1;
}
//找下一个邻接点
p=p->nextarc;
}
}
}
- 【思想】假设图G采用邻接表存储结构。利用广度优先遍历算法。从v出发进行广度遍历时,最后一层的顶点距离v最远。遍历时利用队列逐层暂存各个顶点,队列中的最后一个顶点k一定在最后一层,因此只要将该节点作为结果即可。对应的算法如下:
int maxdist(AGraph *G,int v)
{
ArecNode *p;
//队列及首尾指针
int Qu[MAXV],front=0,rear=0;
int visited[MAXV];
int i,j,k;
//初始化访问数组
for(i=0;i<G->n;i++)
visited[i]=0;
rear++;
//顶点v进队
Qu[rear]=v;
visited[v]=1;
while(rear!=front)
{
front=(front+1)%MAXV;
//顶点出队
k=Qu[front];
//找第一个邻接点
p=G->adjlist[k].firstarc;
//所有未访问过的邻接点进队
while(p)
{
j=p->adjvex;
if(visited[j]==0)
{
visited[j]=1;
rear=(rear+1)%MAXV;
Qu[rear]=j;
}
p=p->nextarc;
}
}
return k;
}
3.【思想】先置全局数组visited[]所有元素为0,然后从顶点i开始进行某种遍历,遍历结束之后,若visited[j]=0,说明顶点i和顶点j之间没有路径;否则说明二者之间存在路径。进而基于DFS遍历的算法如下:
int DFSTrave(AGraph *G,int i,int j)
{
int k;
for(k=0;k<G->n;k++)
visited[k]=0;
DFS(G,i);//从顶点i开始进行深度优先遍历
if(visited[j]==0)
return 0;
else
return 1;
}
int BFSTrave(AGraph *G,int i,int j)
{
int k;
for(k=0;k<G->n;k++)
visited[k]=0;
BFS(G,i);//从顶点i开始进行广度优先遍历
if(visited[j]==0)
return 0;
else
return 1;
}
- 代码如下
void Dijkstra(MGraph g,int v)
{
int dist[MAXV];
int path[MAXV];
int S[MAXV];
int mindis;
int i,j,u=0;
for(i=0;i<g.n;i++)
{
dist[i]=g.edges[v][i];//距离初始化
S[i]=0;
if(g.edges[v][i]<INF)//路径初始化
path[i]=v;//顶点v到i有边 置顶点i的前一个顶点为v
else
path[i]=-1;//顶点v到i无边 置顶点i的前一个顶点为-1
}
S[v]=1; //源点v放入S中
for(i=0;i<g.n-1;i++)
{
mindis=INF;
for(j=0;j<g.n;j++)
{
if(S[j]==0 && dist[j]<mindis)
{
u=j;
mindis=dist[j];
}
}
printf("将顶点%d放入S中\n", u);
S[u]=1;
for (j=0;j<g.n;j++)
{
if(S[j]==0)
{
if (g.edges[u][j]<INF && dist[u]+g.edges[u][j]<dist[i])
{
dist[j] = dist[u]+g.edges[u][j];
path[j]=u;
}
}
}
}
DispAllPath(g,dist,path,S,v);
}
void DispAllPath(MGraph g,int dist[],int path[],int S[],int v)
{
int i,j,k;
int apath[MAXV],d;
for(i=0;i<g.n;i++)
{
if(S[i]==1 && i!=v)
{
printf("从%d到%d的最短路径长度为:%d\t 路径:",v,i,dist[i]);
d=0;
apath[d]=i;
k=path[i];
if(-1 == k)
printf("无路径!\n");
else
{
while(k != v)
{
d++;
apath[d]=k;
k=path[k];
}
d++;
apath[d]=v;
printf("%d",apath[d]);
for(j=d-1;j>=0;j--)
{
printf("->%d",apath[j]);
}
printf("\n");
}
}
}
}
- (1)思想如下:
代码如下:
void InDs(AGraph *G)
{
ArcNode *p;
//数组A存放各顶点的入度
int A[MAXV],i;
//初始时A中元素初值为0
for(i=0;i<G->n;i++)
A[i]=0;
//扫描所有顶点表节点
for(i=0;i<G->n;i++)
{
p=G->adjlist[i].firstarc;
while(p)
{
A[p->adjvex]++;
p=p->nextarc;
}
}
printf("各顶点的入度:\n");
for(i=0;i<G->n;i++)
printf(" 顶点%d:%d\n",i,A[i]);
}
(2)思想如下:扫描邻接表,对于顶点i,记录各顶点的边数n,并输出。对应算法如下:
void OutDs(AGraph *G)
{
ArcNode *p;
int i,n;
printf("各顶点的出度:\n");
for(i=0;i<G->n;i++)
{
n=0;
p=G->adjlist[i].firstarc;
while(p)
{
n++;
p=p->nextarc;
}
printf(" 顶点%d:%d\n",i,n);
}
}
(3)【思想】用MAXds记录最大出度数,MAXv记录最大出度顶点。扫描邻接表,对于顶点i,记录各顶点的边数n,与MAXds比较,将较大者保存到MAXds中,最后输出之。对应算法如下
void MaxOutDs(AGraph *G)
{
int MAXv=0;
int MAXds=0;
int i,n;
ArecNode *p;
for(i=0;i<G->n;i++)
{
p=G->adjlist[i].firstarc;
n=0;
while(p)
{
n++;
p=p->nextarc;
}
if(n>MAXds)
{
MAXds=n;
MAXv=i;
}
}
printf(" 最大出度:顶点%d的出度=%d\n",MAXv,MAXds);
}
(4)【思想】扫描邻接表,对于顶点i,记录各顶点的边数n,当n为0时输出之。对应算法如下:
void ZeroOutDs(AGraph *G)
{
int i,n;
ArcNode *p;
printf("出度为0的顶点:");
for(i=0;i<G->n;i++)
{
p=G->adjlist[i].firstarc;
n=0;
while(p)
{
n++;
p=p->nextarc;
}
if(0==n)
printf("%d\n",i);
}
printf("\n")
}
(5)【思想】扫描邻接表,对于顶点i,若其单链表中存在顶点j,表示顶点i到顶点j有边,否则无边。对应算法如下:
void Arc(AGraph *G,int i,int j)
{
ArcNode *p;
p=G->adjlist[i].firstarc;
while(p && p->adjvex!=j)
p=p->nextarc;
if(p==NUL)
printf("不存在%d到%d的边\n",i,j);
else
printf("存在%d到%d的边\n",i,j);
}
六、说明
本人已毕业多年,读研时撰写了一份 《数据结构与算法分析(C++语言版)_张琨版 课后习题答案》,每年依旧有大量考研的学弟学妹们来找这份答案,现将其公布在blog上,仅供学术交流,上述解答如有问题,可私信沟通。