李春葆《数据结构》-课后习题代码题

一:假设不带权有向图采用邻接矩阵 g 存储,设计实现以下功能的算法:

1)求出图中每个顶点的入度。

代码:
void indegree(MatGraph g){
	int i,j,n;
	printf("各个顶点的入度:\n");
	for(int j=0;j<g.n;j++){
		n=0;
		for(int i=0;i<g.n;i++){
			if(g.edges[i][j]!=0){
				n++;
			}
		}
		printf(" 顶点%d:%d\n",j,n);
	}
}

2)求出图中每个顶点的出度。

代码:
void outdegree(MatGraph g){
	int i,j,n;
	printf("各个顶点的出度:\n");
	for(int i=0;i<g.n;i++){
		n=0;
		for(int j=0;j<g.n;j++){
			if(g.edges[i][j]!=0){
				n++;
			}
		}
		printf(" 顶点%d:%d\n",i,n);
	}
}

3)求出图中出度为0的顶点数。

代码:
void zeroOutdegree(MatGraph g){
	int i,j,n;
	printf("出度为0的顶点:\n");
	for(int i=0;i<g.n;i++){
		n=0;
		for(int j=0;j<g.n;j++){
			if(g.edges[i][j]!=0){
				n++;
			}
		}	
		if(n==0)
			printf("%d\n",i);
	}
	printf("\n");
}

二:假设不带权有向图采用邻接表 G 存储,设计实现以下功能的算法:

1)求出图中每个顶点的入度。

代码:
void indegree(AdjGraph *g){
	ArcNode *p;
	int A[MAX],i;
	for(i=0;i<g->n;i++){
		A[i]=0;
	}
	for(i=0;i<g->n;i++){//扫描所有头结点
		p=g->adjlist[i].firstarc;
		while(p!=NULL){
			A[p->adjvex]++;//表示 i 到 p->adjvex 顶点有一条边
			p=p->nextarc;
		}
	}
	printf("各个顶点的入度:\n");
	for(i=0;i<g->n;i++){
		printf(" 顶点%d:%d\n",i,A[i]);
	}
}

2)求出图中每个顶点的出度。

代码:
void outdegree(AdjGraph *g){
	ArcNode *p;
	int i,n;
	printf("各个顶点的出度:\n");
	for(i=0;i<g->n;i++){
		n=0;
		p=g->adjlist[i].firstarc;
		while(p!=NULL){
			n++;
			p=p->nextarc;
		}
		printf(" 顶点%d:%d\n",i,n);
	} 
}

3)求出图中出度为0的顶点数。

代码:
void zeroOutdegree(AdjGraph *g){
	ArcNode *p;
	int i,n;
	printf("各出度为0的顶点:\n");
	for(i=0;i<g->n;i++){
		n=0;
		p=g->adjlist[i].firstarc;
		while(p!=NULL){
			n++;
			p=p->nextarc;
		}
		if(n==0){
			printf("%d\n",i);
		}
	} 
	printf("\n");
}

三:假设一个连通图采用邻接表作为存储结构,试设计一个算法,判断其中是否存在经过顶点 v 的回路。

思想:利用深度优先遍历。从顶点 v 出发进行深度优先遍历,用 d 记录走过的路径长度,对每个访问的顶点设置标记为 1。若当前访问顶点 u,表示 vu 存在一条路径,如果顶点 u 的邻接点 w 等于 v 并且 d>1,表示顶点 u v 有一条边,即构成经过顶点 v 的回路。Cycle 算法中 has 是布尔值,初始调用时置为 false,执行后若为 true 表示存在经过顶点 v 的回路, 否则表示没有相应的回路。

代码:

int visited[Max];//全局变量
void Cycle(AdjGraph *G,int u,int v,int d,int &has){
	//has初始为false,d=-1 
	int w,i;
	ArcNode *p;
	visited[u]=1;
	d++;
	p=G->adjlist.firstarc;
	while(p!=NULL){
		w=p->adjvex;
		if(visited[w]==0){//若顶点 w 未访问,递归访问它
			Cycle(G,w,v,d,has);
		}else if (w=v&&d>1){//u 到 v 存在一条边且回路长度大于 1
			has=true;
			return;
		}
		p=p->nextarc;//找下一个邻接点
	}
}
bool FindCyclePath(AdjGraph *G,int k){
	bool has = false;
	Cycle(G,v,v,-1,has);
	return has;
}

四:假设图 G 采用邻接表存储,试设计一个算法,判断无向图 G 是否是一棵树。若是树,返回真;否则返回假。

思想:一个无向图 G 是一棵树的条件是:G 必须是无回路的连通图或者是有 n-1 条边的 连通图。这里采用后者作为判断条件,通过深度优先遍历图 G,并求出遍历过的顶点数 vn 和边数 en,若 vn==G->n 成立(表示为连通图)且 en==2*(G->n-1)(遍历边数为 2*(G->n-1))成立,则 G 为一棵树。

代码:

//先求无向图的顶点数和边数
void DFS(AdjGraph *G,int v,int &vn,int &en){
	ArcNode *p;
	visited[v]=1;vn++;
	p=p->adjvex[v].firstarc;
	while(p!=NULL){
		en++;
		if(visited[p->adjvex]==0){
			DFS(G,p->adjvex,vn,en);
		}
		p=p->nextarc;
	}
} 
//判断是否为一棵树 
int IsTree(AdjGraph *G){
	int vn=0,en=0,i;
	int visited[MAX];
	for(i=0;i<G->n;i++){
		visited[i]=0;
	}
	DFS(G,1,vn,en);
	if(vn==G->n&&en==2*(G->n-1)){
		return 1;
	}else{
		return 0;
	}
}
五:设有 5 地( 0 4 )之间架设有 6 座桥( A F ),如图 所示,设计一个算法,
从某一地出发,经过每座桥恰巧一次,最后仍回到原地。

思想:该实地图对应的一个无向图 G 如图所示,本题变为从指定点 k 出发找经过所有 6 条边回到 k 顶点的路径。

代码:
int vedge[MAXV][MAXV]; //边访问数组,vedge[i][j]表示(i,j)边是否访问过
void Traversal(AdjGraph *G, int u, int v, int k, int path[], int d) {
	//开始时,d=-1 
    int w,i;
    ArcNode *p;
    d++;
    path[d] = v; // (u,v) 加入到 path 中
    vedge[u][v] = vedge[v][u] = 1; // (u,v) 边已访问
    p = G->adjlist[v].firstarc; // p 指向顶点 v 的第一条边
    while (p != NULL) {
        w = p->adjvex; // (v,w) 有一条边
        if (w == k && d == G->e - 1) { // 找到一个回路,输出之
            printf(" %d->", k);
            for (i = 0; i <= d; i++) {
                printf("%d->", path[i]);
            }
            printf("%d\n", w);
        }
        if (vedge[v][w] == 0) { // (v,w) 未访问过,则递归访问之
            Traversal(G, v, w, k, path, d);
        }
        p = p->nextarc; // 找 v 的下一条边
    }
    vedge[u][v] = vedge[v][u] = 0; // 恢复环境:使该边点可重新使用
}

void FindCPath(AdjGraph *G, int k) { // 输出经过顶点 k 和所有边的全部回路
    int path[MAXV];
    int i, j, v;
    ArcNode *p;
    for (i = 0; i < G->n; i++) {
    	// vedge 数组置初值
        for (j = 0; j < G->n; j++)
            if (i == j) vedge[i][j] = 1;
            else vedge[i][j] = 0;
	}
    printf("经过顶点%d 的走过所有边的回路:\n", k);
    p = G->adjlist[k].firstarc;
    while (p != NULL) {
        v = p->adjvex;
        Traversal(G, k, v, k, path, -1);
        p = p->nextarc;
    }
}

六:设不带权无向图 G 采用邻接表表示,设计一个算法求源点 i 到其余各顶点的最短路径。

思想: 利用广度优先遍历的思想,求 i j 两顶点间的最短路径转化为求从 i j 的层数,
为此设计一个 level [] 数组记录每个顶点的层次。
代码:
void ShortPath(AdjGraph *G, int i) {
    int qu[MAX], level[MAX]; // 队列和层次数组
    int front = 0, rear = 0, k, lev; // k 保存当前顶点,lev 保存从 i 到访问顶点的层数
    ArcNode *p; // 边节点指针
    visited[i] = 1; // 标记顶点 i 已访问
    rear++; qu[rear] = i; level[rear] = 0; // 将顶点 i 入队,初始层次为 0

    while (front != rear) { // 当队列不为空时执行
        front = (front + 1) % MAX; // 出队操作
        k = qu[front]; // 获取队首元素
        lev = level[front]; // 获取该元素的层次

        if (k != i) {
            printf("顶点%d 到顶点%d 的最短距离是:%d\n", i, k, lev); // 打印从 i 到 k 的最短距离
        }

        p = G->adjlist[k].firstarc; // 获取顶点 k 的邻接表头指针
        while (p != NULL) { // 遍历 k 的所有邻接点
            if (visited[p->adjvex] == 0) { // 如果邻接点未被访问过
                visited[p->adjvex] = 1; // 标记为已访问
                rear = (rear + 1) % MAXV; // 入队操作
                qu[rear] = p->adjvex; // 将邻接点入队
                level[rear] = lev + 1; // 更新层次
            }
            p = p->nextarc; // 移动到下一个邻接点
        }
    }
}

七: 对于一个带权有向图,设计一个算法输出从顶点 i 到顶点 j 的所有路径及其路径长度。调用该算法求出图中顶点 0 到顶点 3 的所有路径及其长度。

代码:

int visited[MAX]; //用于标记顶点是否被访问过
void findpath(AdjGraph *G, int u, int v, int path[], int d, int length) {
    // d 表示 path 中顶点个数,初始为 0;length 表示路径长度,初始为 0
    int w, i;
    ArcNode *p;
    path[d] = u; // 将顶点 u 加入到路径中
    d++; // 顶点数增 1
    visited[u] = 1; // 标记顶点 u 已访问
    
    if (u == v && d > 0) { // 如果找到一条路径且路径非空
        printf("路径长度:%d, 路径:", length);
        for (i = 0; i < d; i++) {
            printf("%2d", path[i]);
        }
        printf("\n");
    }
    
    p = G->adjlist[u].firstarc; // p 指向顶点 u 的第一个邻接点
    while (p != NULL) {
        w = p->adjvex; // w 为顶点 u 的邻接点
        if (visited[w] == 0) { // 如果 w 顶点未访问,递归访问它
            findpath(G, w, v, path, d, p->weight + length);
        }
        p = p->nextarc; // p 指向顶点 u 的下一个邻接点
    }
    
    visited[u] = 0; // 恢复环境,使该顶点可重新使用
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/920932.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

wsl安装

一. wsl简介 1. wsl和wsl2的区别 wsl需要把linux命令翻译为windows命令&#xff0c;性能差一些。 wsl2直接使用linux内核&#xff0c;不需要翻译&#xff0c;性能好&#xff0c;但开销相对大一点&#xff0c;因为需要多运行一个hyper-v虚拟机 (并非完整的虚拟机&#xff0c;是…

Java-06 深入浅出 MyBatis - 一对一模型 SqlMapConfig 与 Mapper 详细讲解测试

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; 大数据篇正在更新&#xff01;https://blog.csdn.net/w776341482/category_12713819.html 目前已经更新到了&#xff1a; MyBatis&#xff…

GPT中转站技术架构

本文介绍阿波罗AI中转站&#xff08;https://api.ablai.top/&#xff09;的技术架构&#xff0c;该中转API的技术架构采用了分布式架构、智能调度和API中转等技术&#xff0c;确保了全球范围内的高效访问和稳定运行。以下是对该技术架构的详细分析&#xff1a; 分布式架构 分…

远程服务器Docker使用本地代理加速访问外部资源

Docker在pull镜像的时候非常缓慢&#xff0c;但是远程主机没有安装代理&#xff0c;就很为难&#xff0c;现在分享一个可以让远程服务器使用本地代理加速的方法 配置Docker代理 新建文件夹 mkdir -p /etc/systemd/system/docker.service.d 切换到这个文件夹里 cd /etc/system…

【详解】树链剖分之重链剖分

终于搞懂了树链剖分的一些皮毛了…… 树链剖分 “树链剖分”&#xff0c;顾名思义&#xff0c;就是把一棵树剖分成一条条的链…… 重链剖分 重链剖分的基本概念 重链剖分是树链剖分的一种&#xff0c;它会把树剖分成一条条重链…… 什么是重链呢&#xff1f; 重链就是连接…

RocketMQ: 部署结构与存储特点

RocketMQ 是什么 它是一个队列模型的消息中间件&#xff0c;具有高性能、高可靠、高实时、分布式特点 Producer、Consumer、队列都可以分布式Producer 向一些队列轮流发送消息 队列集合称为 TopicConsumer 如果做广播消费则一个 consumer 实例消费这个 Topic 对应的所有队列如果…

帮助中心FAQ系统:打造卓越客户服务体验的关键驱动力

在当今这个信息爆炸的时代&#xff0c;企业为了保持市场竞争力&#xff0c;必须不断提升客户服务体验。FAQ&#xff08;常见问题解答&#xff09;系统&#xff0c;作为一种高效且便捷的用户服务工具&#xff0c;正日益受到企业的青睐。本文将阐述FAQ系统的核心价值、功能特性以…

如何使用 Python 开发一个简单的文本数据转换为 Excel 工具

目录 一、准备工作 二、理解文本数据格式 三、开发文本数据转换为Excel工具 读取CSV文件 将DataFrame写入Excel文件 处理其他格式的文本数据 读取纯文本文件&#xff1a; 读取TSV文件&#xff1a; 四、完整代码与工具封装 五、使用工具 六、总结 在数据分析和处理的…

Elasticsearch向量搜索:从语义搜索到图搜图只有一步之遥

续 上集说到语义搜索&#xff0c;这集接着玩一下图搜图&#xff0c;这种场景在电商中很常见——拍照搜商品。图搜图实现非常类似语义搜索&#xff0c;代码逻辑结构都很类似… 开搞 还是老地方modelscope找个Vision Transformer模型&#xff0c;这里选用vit-base-patch16-224…

Flink【基于时间的双流联结 Demo】

前言 1、基于时间的双流联结&#xff08;Join&#xff09; 对于两条流的合并&#xff0c;很多情况我们并不是简单地将所有数据放在一起&#xff0c;而是希望根据某个字段的值将它们联结起来&#xff0c;“配对”去做处理。例如用传感器监控火情时&#xff0c;我们需要将大量温度…

大数据入门-什么是Flink

这里简单介绍Flink的概念、架构、特性等。至于比较详细的介绍&#xff0c;会单独针对这个组件进行详细介绍&#xff0c;可以关注博客后续阅读。 一、概念 Apache Flink 是一个框架和分布式处理引擎&#xff0c;用于在无边界和有边界数据流上进行有状态的计算。 Flink的四大基…

KubeVirt下gpu operator实践(GPU直通)

KubeVirt下gpu operator实践(GPU直通) 参考《在 KubeVirt 中使用 GPU Operator》&#xff0c;记录gpu operator在KubeVirt下实践的过程&#xff0c;包括虚拟机配置GPU直通&#xff0c;容器挂载GPU设备等。 KubeVirt 提供了一种将主机设备分配给虚拟机的机制。该机制具有通用性…

How to update the content of one column in Mysql

How to update the content of one column in Mysql by another column name? UPDATE egg.eggs_record SET sold 2024-11-21 WHERE id 3 OR id 4;UPDATE egg.eggs_record SET egg_name duck egg WHERE id 2;

【K8S系列】imagePullSecrets配置正确,但docker pull仍然失败,进一步排查详细步骤

如果 imagePullSecrets 配置正确,但在执行 docker pull 命令时仍然失败,可能存在以下几种原因。以下是详细的排查步骤和解决方案。 1. 检查 Docker 登录凭证 确保你使用的是与 imagePullSecrets 中相同的凭证进行 Docker 登录: 1.1 直接登录 在命令行中,执行以下命令: …

机器学习基础06

目录 1.梯度下降 1.1梯度下降概念 1.2梯度下降公式 1.3学习率 1.4实现梯度下降 1.5API 1.5.1随机梯度下降SGD 1.5.2小批量梯度下降MBGD 1.6梯度下降优化 2.欠拟合过拟合 2.1欠拟合 2.2过拟合 2.3正则化 2.3.1L1正则项&#xff08;曼哈顿距离&#xff09; 2.3.2…

徒手从零搭建一套ELK日志平台

徒手从零搭建一套ELK日志平台 日志分析的概述日志分析的作用主要收集工具集中式日志系统主要特点采集日志分类ELK概述初级版ELK终极版ELK高级版ELKELK收集日志的两种形式 搭建ELK平台Logstash工作原理Logstash核心概念环境准备安装部署docker添加镜像加速器安装部署Elasticsear…

开源科学工程技术软件介绍 – EDA工具KLayout

link 今天向各位知友介绍的 KLayout是一款由德国团队开发的开源EDA工具。 KLayout是使用C开发的&#xff0c;用户界面基于Qt。它支持Windows、MacOS和Linux操作系统。安装程序可以从下面的网址下载&#xff1a; https://www.klayout.de/build.html KLayout图形用户界面&…

Linux离线安装Docker命令,简单镜像操作

解压安装包 首先&#xff0c;使用 tar 命令解压 docker-27.3.1.tgz 安装包&#xff1a; tar -zxvf docker-27.3.1.tgz 将二进制文件移动到可执行路径上的目录 接着&#xff0c;将解压出来的 Docker 二进制文件复制到系统的可执行路径&#xff08;通常是 /usr/bin/&#xff09…

Redis中常见的数据类型及其应用场景

五种常见数据类型 Redis中的数据类型指的是 value存储的数据类型&#xff0c;key都是以String类型存储的&#xff0c;value根据场景需要&#xff0c;可以以String、List等类型进行存储。 各数据类型介绍&#xff1a; Redis数据类型对应的底层数据结构 String 类型的应用场景 常…

redis中的set类型及常用命令

集合就是把一些有关联的数据放到一起。与list不同的是&#xff0c;集合中的顺序不重要&#xff0c;变换了元素的顺序&#xff0c;仍是同一个集合。集合中的元素是不能重复的。和list类似&#xff0c;集合中的每个元素&#xff0c;也都是string类型。 关于集合的相关命令 sadd/…