数据结构与算法分析(C++语言版)_张琨版 第七章图课后习题答案

一、选择题

  1. B 2.A 3.B 4.C 5.D 6.A 7.D 8.B 9.D 10.B

二、填空题

在这里插入图片描述

三、判断题

  1. × 例如,一个有向图G=(V,E),V={0,1,2,3},E={<0,1>,<1,2>,<2,3>,❤️,0>},则可以从任一顶点访问到每个顶点,但该图却非完全图
  2. × 广度优先遍历算法适合于有向图和无向图
  3. √ 任何一条边计入一个顶点的入度和另一个顶点的出度
  4. × 最大出度为n
  5. × 一个有向图G=(V,E),V={0,1,2},E={<0,1>,<1,0>,<1,2>,<2,1>},该图的邻接矩阵是一个对称矩阵,但该有向图不是完全有向图
  6. × 只有减少所有关键路径中的公共活动的权值时,整个工期才可能减少

四、简答题

在这里插入图片描述

五、计算题

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;
		}
	}
}
  1. 【思想】假设图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;

}
  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. (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上,仅供学术交流,上述解答如有问题,可私信沟通。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

赵卓不凡

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值