数据结构上机实验——图的实现(以无向邻接表为例)、图的深度优先搜索(DFS)、图的广度优先搜索(BFS)

文章目录

  • 数据结构上机实验
    • 1.要求
    • 2.图的实现(以无向邻接表为例)
      • 2.1创建图
        • 2.1.1定义图的顶点、边及类定义
        • 2.1.2创建无向图和查找
        • 2.1.3插入边
        • 2.1.4打印函数
      • 2.2图的深度优先搜索(DFS)
      • 2.3图的广度优先搜索(BFS)
    • 3.全部源码
      • 测试:
      • Graph.h
      • test.cpp

数据结构上机实验

1.要求

  图采用邻接表存储结构,编程实现图的深度优先搜索和广度优先搜索算法。
            

2.图的实现(以无向邻接表为例)

2.1创建图

2.1.1定义图的顶点、边及类定义

  我们定义一个邻接表类(ALGraph)。这里实现一些基础的数据结构。要注意结构体的嵌套。

  Edge: 用于表示图中的边,包含两个顶点(tail和head)和一个权重cost。

  ArcNode: 用于表示图中的有向边,包含一个目标顶点adjvex、一个权重info和一个指向下一个有向边的指针nextarc。

  VNode: 用于表示图中的顶点,包含一个数据值data和一个指向第一条边的指针fistarc。

  AdjGraph: 用于表示整个图,包含一个顶点数组表vertices(最大顶点数为MAXVex)、顶点数vexnum、边数arcnum和图的类型kind。

#define MAXVex 20 //最大的顶点数	
#define VElemType inttypedef enum {DG,    //有向图UDG,   //无向图DN,    //有向网UDN    //无向网
}GraphKind;//定义边
typedef struct 
{VElemType tail;VElemType head;int cost;
}Edge;//定义边节点
typedef struct ArcNode 
{int adjvex;	 //终点在数组表中的下表int info;	 //权值ArcNode* nextarc; //下一个边的地址
}ArcNode;//定义表头节点
typedef struct
{VElemType data;	 ArcNode* fistarc; //储存第一条边的结点地址
}VNode;//定义邻接表
typedef struct
{VNode vertices[MAXVex]; //储存MAXVex个VNode的数组表int vexnum;    //顶点数int arcnum;    //边数GraphKind kind;
}AdjGraph;//定义邻接表类
class ALGraph
{
private:AdjGraph ag;
};

  

2.1.2创建无向图和查找

  CreateGraph函数:

  该函数首先使用输入参数n和m来初始化图的顶点数和边数。它通过循环读入每个顶点的数据,并初始化顶点数组表。每个顶点的数据值被初始化为输入的值,而第一条边的地址被初始化为NULL。 接着,它通过循环读入每条边的信息,并建立边集。对于每条边,它查找两个顶点的位置,然后创建一个新的ArcNode来存储这条边。如果图是无向的(kind == UDN),它还会创建另一个ArcNode来存储反向边。

  LocateVex函数:

  这个函数用于查找给定数据值在顶点数组表中的位置。 它遍历整个顶点数组表,如果找到匹配的数据值,就返回该位置的索引;否则,返回-1。

//创建无向图
void CreateGraph(int n, int m)
{ag.vexnum = n;  //ag有n个顶点ag.arcnum = m;  //ag有m个边ag.kind = UDN;int i, j, w, h, t;VElemType u, v;ArcNode* p;for (i = 0; i < n; i++)  //初始化顶点数组表{cin >> ag.vertices[i].data;ag.vertices[i].fistarc = NULL;}for (j = 0; j < m; j++) //建立边集{cin >> u >> v >> w;  //输入一条弧<u,v,w>h = LocateVex(u);t = LocateVex(v);p = new ArcNode;  //储存无向边p->adjvex = t;p->info = w;p->nextarc = ag.vertices[h].fistarc;if (ag.kind == UDN)  //储存无向边(v,u){ag.vertices[h].fistarc = p;p = new ArcNode;p->adjvex = h;p->info = w;p->nextarc = ag.vertices[t].fistarc;ag.vertices[t].fistarc = p;}}
}//查找顶点信息在数组中的下表
int LocateVex(VElemType u)
{for (int i = 0; i < ag.vexnum; i++){if (u == ag.vertices[i].data){return i;}}return -1;
}

  

2.1.3插入边

  InsertArcGraph:

  接受三个参数:顶点u、顶点v和边的权重info。代码实现了向图中插入新的边的功能。如果指定的两个顶点不存在,则会在顶点数组表中插入它们。 然后,创建两个新的ArcNode节点来代表双向边,并将它们插入到两个顶点的第一条边链表中。最后,更新图的状态信息(顶点数和边数)。

//插入边
void InsertArcGraph(VElemType u, VElemType v, int info)
{int h = LocateVex(u), t = LocateVex(v);ArcNode* p;if (h == -1)  //在顶点数组表中插入顶点u{ag.vertices[ag.vexnum].data = u;ag.vertices[ag.vexnum].fistarc = NULL;h = ag.vexnum;ag.vexnum++;}if (t == -1)  //在顶点数组表中插入顶点t{ag.vertices[ag.vexnum].data = v;ag.vertices[ag.vexnum].fistarc = NULL;t = ag.vexnum;ag.vexnum++;}p = new ArcNode;p->adjvex = t;p->info = info;p->nextarc = ag.vertices[h].fistarc;ag.vertices[h].fistarc = p;p = new ArcNode;p->adjvex = h;p->info = info;p->nextarc = ag.vertices[t].fistarc;ag.vertices[t].fistarc = p;ag.arcnum++;
}

  

2.1.4打印函数

  Print()

  这段代码是一个用于打印图的顶点和边信息的函数。 它遍历图的顶点数组表和邻接表,并打印每个顶点的索引、数据值和邻居信息。输出格式可以帮助理解图的结构和连接关系。

//打印函数
void Print()
{// 顶点for (size_t i = 0; i < ag.vexnum; ++i){cout << "[" << i << "]" << "->" << ag.vertices[i].data << endl;}cout << endl;for (size_t i = 0; i < ag.vexnum; ++i){cout << ag.vertices[i].data << "[" << i << "]->";ArcNode* cur = ag.vertices[i].fistarc;while (cur){cout << "[" << cur->adjvex << ":" << cur->info << "]->";cur = cur->nextarc;}cout << "NULL" << endl;}cout << endl;
}

  

2.2图的深度优先搜索(DFS)

  深度优先搜索(DFS)是一种用于遍历或搜索树或图的算法。这个算法会尽可能深地搜索图的分支。当节点v的所在边都己被探寻过,搜索将回溯到发现节点v的那条边的起始节点

  实现图的深度优先搜索(DFS)的算法。我们使用递归即可,同时要使用数组vis来追踪哪些节点已经被访问过。

  在DFS函数中,我们应该使用节点的索引进行访问和标记,如果遇到了没有标记的点,就进行DFS操作,直到遍历完我们所有的图即可。
在这里插入图片描述

//深度优先搜索
int vis[MAXVex];
void DFS(VElemType v)
{ArcNode* p;int h = LocateVex(v);cout << v;vis[h] = 1;for (p = ag.vertices[h].fistarc; p; p = p->nextarc){if (vis[p->adjvex] == 0){DFS(ag.vertices[p->adjvex].data);}}
}
void DFSTraverse()
{int i;for (i = 0; i < ag.vexnum; i++){vis[i] = 0;}for (i = 0; i < ag.vexnum; i++){if (!vis[i]){DFS(ag.vertices[i].data);}}cout << endl;
}

  

2.3图的广度优先搜索(BFS)

  广度优先搜索(BFS)是一种用于图的遍历或搜索的算法。这种算法会尽可能广地搜索图的节点,从一个起始节点开始,探索邻近节点,然后再探索下一层级的节点。

  图的广度优先搜索(BFS)算法,我们可以利用队列来实现,它是在图中查找从给定源节点到所有其他节点的路径的算法。在的代码中,我们需要定义了一个数组visi来跟踪已经访问过的节点,然后使用队列lq来存储待访问的节点。

  在BFSTraverse函数中,我们先初始化visi数组,然后遍历所有的节点。如果一个节点尚未被访问,你就调用BFS函数进行访问。使用传递进来的节点数据来查找其在图中的索引,然后不断重复操作,知道队列中的数据为0。
在这里插入图片描述

//广度优先搜索
int visi[MAXVex];
void BFS(VElemType v)
{int h = LocateVex(v);ArcNode* p;queue<VElemType> lq;lq.push(h);visi[h] = 1;while (!lq.empty()){h=lq.front();lq.pop();cout << ag.vertices[h].data;for (p = ag.vertices[h].fistarc; p; p = p->nextarc){if (!visi[p->adjvex]){lq.push(p->adjvex);visi[p->adjvex] = 1;}}}
}
void BFSTraverse()
{int i;for (i = 0; i < ag.vexnum; i++){visi[i] = 0;}for (i = 0; i < ag.vexnum; i++){if (!visi[i]){BFS(ag.vertices[i].data);}}cout << endl;
}

            

3.全部源码

测试:

在这里插入图片描述

完全联通图示例:

在这里插入图片描述

有孤立点的示例:

在这里插入图片描述

  

Graph.h

#pragma once#include<queue>namespace link_table
{
#define MAXVex 20 //最大的顶点数	
#define VElemType inttypedef enum {DG,    //有向图UDG,   //无向图DN,    //有向网UDN    //无向网
}GraphKind;//定义边
typedef struct 
{VElemType tail;VElemType head;int cost;
}Edge;//定义边节点
typedef struct ArcNode 
{int adjvex;	 //终点在数组表中的下表int info;	 //权值ArcNode* nextarc; //下一个边的地址
}ArcNode;//定义表头节点
typedef struct
{VElemType data;	 ArcNode* fistarc; //储存第一条边的结点地址
}VNode;//定义邻接表
typedef struct
{VNode vertices[MAXVex]; //储存MAXVex个VNode的数组表int vexnum;    //顶点数int arcnum;    //边数GraphKind kind;
}AdjGraph;//定义邻接表类
class ALGraph
{
public://创建无向图void CreateGraph(int n, int m){ag.vexnum = n;  //ag有n个顶点ag.arcnum = m;  //ag有m个边ag.kind = UDN;int i, j, w, h, t;VElemType u, v;ArcNode* p;for (i = 0; i < n; i++)  //初始化顶点数组表{cin >> ag.vertices[i].data;ag.vertices[i].fistarc = NULL;}for (j = 0; j < m; j++) //建立边集{cin >> u >> v >> w;  //输入一条弧<u,v,w>h = LocateVex(u);t = LocateVex(v);p = new ArcNode;  //储存无向边p->adjvex = t;p->info = w;p->nextarc = ag.vertices[h].fistarc;if (ag.kind == UDN)  //储存无向边(v,u){ag.vertices[h].fistarc = p;p = new ArcNode;p->adjvex = h;p->info = w;p->nextarc = ag.vertices[t].fistarc;ag.vertices[t].fistarc = p;}}}//查找顶点信息在数组中的下表int LocateVex(VElemType u){for (int i = 0; i < ag.vexnum; i++){if (u == ag.vertices[i].data){return i;}}return -1;}//计算顶点的度数int Degree(VElemType u){int h = LocateVex(u);int count = 0;ArcNode* p = ag.vertices[h].fistarc;while (p){count++;p = p->nextarc;}return count;}//插入边void InsertArcGraph(VElemType u, VElemType v, int info){int h = LocateVex(u), t = LocateVex(v);ArcNode* p;if (h == -1)  //在顶点数组表中插入顶点u{ag.vertices[ag.vexnum].data = u;ag.vertices[ag.vexnum].fistarc = NULL;h = ag.vexnum;ag.vexnum++;}if (v == INT32_MAX) return;if (t == -1)  //在顶点数组表中插入顶点t{ag.vertices[ag.vexnum].data = v;ag.vertices[ag.vexnum].fistarc = NULL;t = ag.vexnum;ag.vexnum++;}p = new ArcNode;p->adjvex = t;p->info = info;p->nextarc = ag.vertices[h].fistarc;ag.vertices[h].fistarc = p;p = new ArcNode;p->adjvex = h;p->info = info;p->nextarc = ag.vertices[t].fistarc;ag.vertices[t].fistarc = p;ag.arcnum++;}//深度优先搜索int vis[MAXVex];void DFS(VElemType v){ArcNode* p;int h = LocateVex(v);cout << v;vis[h] = 1;for (p = ag.vertices[h].fistarc; p; p = p->nextarc){if (vis[p->adjvex] == 0){DFS(ag.vertices[p->adjvex].data);}}}void DFSTraverse(){int i;for (i = 0; i < ag.vexnum; i++){vis[i] = 0;}for (i = 0; i < ag.vexnum; i++){if (!vis[i]){DFS(ag.vertices[i].data);}}cout << endl;}//广度优先搜索int visi[MAXVex];void BFS(VElemType v){int h = LocateVex(v);ArcNode* p;queue<VElemType> lq;lq.push(h);visi[h] = 1;while (!lq.empty()){h=lq.front();lq.pop();cout << ag.vertices[h].data;for (p = ag.vertices[h].fistarc; p; p = p->nextarc){if (!visi[p->adjvex]){lq.push(p->adjvex);visi[p->adjvex] = 1;}}}}void BFSTraverse(){int i;for (i = 0; i < ag.vexnum; i++){visi[i] = 0;}for (i = 0; i < ag.vexnum; i++){if (!visi[i]){BFS(ag.vertices[i].data);}}cout << endl;}//打印函数void Print(){// 顶点for (size_t i = 0; i < ag.vexnum; ++i){cout << "[" << i << "]" << "->" << ag.vertices[i].data << endl;}cout << endl;for (size_t i = 0; i < ag.vexnum; ++i){cout << ag.vertices[i].data << "[" << i << "]->";ArcNode* cur = ag.vertices[i].fistarc;while (cur){cout << "[" << cur->adjvex << ":" << cur->info << "]->";cur = cur->nextarc;}cout << "NULL" << endl;}cout << endl;}private:AdjGraph ag;
};}

  

test.cpp

#define _CRT_SECURE_NO_WARNINGS 1#include<iostream>
using namespace std;#include"Graph.h"void TestGraph1()
{link_table::ALGraph ag;ag.CreateGraph(0, 0);ag.InsertArcGraph(0, 1, 7);ag.InsertArcGraph(0, 2, 3);ag.InsertArcGraph(0, 3, 4);ag.InsertArcGraph(3, 4, 6);ag.InsertArcGraph(1, 2, 5);ag.InsertArcGraph(1, 3, 2);ag.InsertArcGraph(1, 4, 1);ag.InsertArcGraph(2, 4, 7);//创建孤立点,INT32_MAX代表没有连接任何边ag.InsertArcGraph(5, INT32_MAX, 0);cout << "该相邻表为:\n";ag.Print(); cout << "深度优先搜索的结果为:";ag.DFSTraverse();cout << "广度优先搜索的结果为:";ag.BFSTraverse();}int main()
{TestGraph1();return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

为什么PDF文件不能打印?

正常的PDF文件是可以打印的&#xff0c;如果PDF文件打开之后发现文件不能打印&#xff0c;我们需要先查看一下自己的打印机是否能够正常运行&#xff0c;如果打印机是正常的&#xff0c;我们再查看一下&#xff0c;文件中的打印功能按钮是否是灰色的状态。 如果PDF中的大多数功…

使用vue2实现todolist待办事项

个人名片&#xff1a; &#x1f60a;作者简介&#xff1a;一名大二在校生 &#x1f921; 个人主页&#xff1a;坠入暮云间x &#x1f43c;座右铭&#xff1a;懒惰受到的惩罚不仅仅是自己的失败&#xff0c;还有别人的成功。 &#x1f385;**学习目标: 坚持每一次的学习打卡 文章…

Python接口自动化之unittest单元测试

以下主要介绍unittest特性、运行流程及实际案例。 一、单元测试三连问 1、什么是单元测试&#xff1f; 按照阶段来分&#xff0c;一般就是单元测试&#xff0c;集成测试&#xff0c;系统测试&#xff0c;验收测试。单元测试是对单个模块、单个类或者单个函数进行测试。 将…

微信小程序display常用属性和子元素排列方式介绍

wxss中display常用显示属性与css一致&#xff0c;介绍如下&#xff1a; 针对元素本身显示的属性&#xff1a; displayblock&#xff0c;元素显示换行displayinline&#xff0c;元素显示换行&#xff0c;但不可设置固定的宽度和高度&#xff0c;也不可设置上下方向的margin和p…

计算机视觉:人脸识别与检测

目录 前言 识别检测方法 本文方法 项目解析 完整代码及效果展示 前言 人脸识别作为一种生物特征识别技术&#xff0c;具有非侵扰性、非接触性、友好性和便捷性等优点。人脸识别通用的流程主要包括人脸检测、人脸裁剪、人脸校正、特征提取和人脸识别。人脸检测是从获取的图…

ReportLab创建合同PDF

一、前言 有一个项目需要将电子签名后的报价合同和生成的发票发送给客户&#xff0c;这种发送给客户的文件一般都是使用PDF格式&#xff0c;主要是因为PDF特别适合阅读且不同平台打开文件格式不会变形&#xff0c;不过要在程序中生成PDF还是比较麻烦的&#xff0c;我们的发票是…

Fortinet 聚焦核心业务增长领域,巩固网安市场领导地位,持续推动行业创新

近日&#xff0c;专注于推动网络与安全融合的全球网络安全领导者 Fortinet&#xff08;NASDAQ&#xff1a;FTNT&#xff09;发布第三季度财报。同期&#xff0c;Fortinet做出重大战略宣布&#xff0c;未来将重点聚焦高速增长的差异化市场。Fortinet 将紧紧围绕安全组网、Univer…

Jenkins入门——安装docker版的Jenkins 配置mvn,jdk等 使用案例初步 遇到的问题及解决

前言 Jenkins是开源CI&CD软件领导者&#xff0c; 提供超过1000个插件来支持构建、部署、自动化&#xff0c; 满足任何项目的需要。 官网&#xff1a;https://www.jenkins.io/zh/ 本篇博客介绍docker版的jenkins的安装和使用&#xff0c;maven、jdk&#xff0c;汉语的配置…

docker安装AWVS 23.9.231005181

本文声明仅AWVS用作学习使用 将镜像文件secfa_awvs.tar复制到目标机器上。 我的百度网盘文件路径&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1Pe4qlVp9XKbZ3dLrouaP2w 提取码&#xff1a;67mc –来自百度网盘超级会员V6的分享 在目标机器上&#xff0c;使用以下命…

Git-工作流

前言 一、工作流概述二、Git flow1.主要流程2.优缺点3.适用场景 三、Github flow1.主要流程2.优缺点3.适用场景 四、Gitlab flow1.主要流程2.优缺点3.适用场景 总结参考 一、工作流概述 开发人员通过Git可以记录和追踪代码的变化&#xff0c;包括添加、删除和修改文件。如果是…

NLP在网安领域中的应用(初级)

NLP在网安领域的应用 写在最前面NLP在网络安全中的角色案例分析 NLP技术的关键应用最新行业数据和研究1. 威胁情报分析1.1 社交媒体情报分析&#xff08;后面有详细叙述&#xff09;1.2 暗网监测与威胁漏洞挖掘 2. 恶意软件检测2.1 威胁预测与趋势分析 3. 漏洞管理和响应4. 社交…

python数据处理作业4:使用numpy数组对象,随机创建4*4的矩阵,并提取其对角元素

每日小语 真理诚然是一个崇高的字眼&#xff0c;然而更是一桩崇高的业绩。如果人的心灵与情感依然健康&#xff0c;则其心潮必将为之激荡不已。——黑格尔 难点&#xff1a;如何创建&#xff1f;取对角元素的函数是什么&#xff1f; gpt代码学习 import numpy as np# 随机创…

Istio学习笔记-体验istio

参考Istio 入门(三)&#xff1a;体验 Istio、微服务部署、可观测性 - 痴者工良 - 博客园 (cnblogs.com) 在本章中&#xff0c;我们将会学习到如何部署一套微服务、如何使用 Istio 暴露服务到集群外&#xff0c;并且如何使用可观测性组件监测流量和系统指标。 本章教程示例使用…

Haproxy实现七层负载均衡

目录 Haproxy概述 haproxy算法&#xff1a; Haproxy实现七层负载 ①部署nginx-server测试页面 ②(主/备)部署负载均衡器 ③部署keepalived高可用 ④增加对haproxy健康检查 ⑤测试 Haproxy概述 haproxy---主要是做负载均衡的7层&#xff0c;也可以做4层负载均衡 apache也可…

haproxy端口耗尽no free ports

用haproxy配置负载均衡时出现端口不足错误&#xff1b;后端服务连接一会高一会儿低&#xff0c;从0到1w、2w跳变&#xff1b;实际连接数为4w左右&#xff1b; haproxy[8765]: Connect() failed for backend 09e581: no free ports. 问题描述 在请求很少的时候&#xff0c;工作…

VS Code打造Rust的开发环境

文章目录 rust-analyzerCodeLLDB Rust据说是一门永远也不会发生内存错误的语言&#xff0c;并且因其反人类的学习曲线&#xff0c;而长期占据编程鄙视链的最顶端。而且就连微软都准备把Windows挪到Rust上面&#xff0c;可见其受欢迎程度。 rust-analyzer 在插件栏中直接搜索r…

hadoop 大数据集群环境配置 配置hadoop配置文件 hadoop(七)

1. 虚拟机的三台机器分别以hdfs 存储, mapreduce计算&#xff0c;yarn调度三个方面进行集群配置 hadoop 版本3.3.4 官网&#xff1a;Hadoop – Apache Hadoop 3.3.6 jdk 1.8 三台机器尾号为&#xff1a;22&#xff0c; 23&#xff0c; 24。&#xff08;没有用hadoop102, 103,10…

Mybatis报错找不到参数解决之编译保留参数名称

Hi, I’m Shendi Mybatis报错找不到参数解决之编译保留参数名称 需求场景 在使用 Mybatis 的过程中&#xff0c;对于函数参数&#xff0c;通常会加上 Param 注解来给参数命名&#xff0c;以让 Mybatis 找到参数。 有的时候忘记添加&#xff0c;执行时就会报找不到参数的错误&…

STM32——端口复用与重映射概述与配置(HAL库)

文章目录 前言一、什么是端口复用&#xff1f;什么是重映射&#xff1f;有什么区别&#xff1f;二、端口复用配置 前言 本篇文章介绍了在单片机开发过程中使用的端口复用与重映射。做自我学习的简单总结&#xff0c;不做权威使用&#xff0c;参考资料为正点原子STM32F1系列精英…

超越任务调度的极致:初探分布式定时任务 XXL-JOB 分片广播

XXL-JOB 是一个分布式任务调度平台&#xff0c;支持分片任务执行。 1. 依赖引入 在项目中引入 XXL-JOB 的相关依赖。通常&#xff0c;你需要在项目的 pom.xml 文件中添加如下依赖&#xff1a; <dependency><groupId>com.xuxueli</groupId><artifactId&…