【数据结构】图的基本操作——图的构造(邻接矩阵,邻接表),遍历(DFS,BFS)
邻接矩阵实现如下:
/*
主题:用邻接矩阵实现 DFS(递归) 与 BFS(非递归)
作者:Laugh
语言:C++
*******************************************
样例输出如下:
请选择图的类型(a - 无向图, b - 有向图):a
请输入总顶点数,总边数:8 9
请依次输入点的信息:a b c d e f g h
输入一条边依附的顶点及权值 (eg: a b 6):
a b 1
a c 1
b d 1
b e 1
d h 1
e h 1
c f 1
c g 1
f g 1
打印邻接矩阵:
0 1 1 0 0 0 0 0
1 0 0 1 1 0 0 0
1 0 0 0 0 1 1 0
0 1 0 0 0 0 0 1
0 1 0 0 0 0 0 1
0 0 1 0 0 0 1 0
0 0 1 0 0 1 0 0
0 0 0 1 1 0 0 0
请选择遍历方式(1.深度优先搜索; 2.广度优先搜索):
1
DFS:a b d h e c f g
BFS: a b c d e f g h
*/
#include <iostream>
#include <queue>
using namespace std;
#define OK 1
typedef int Status;
/* ————图的邻接矩阵存储表示 ————*/
#define MaxInt 32767 // 表示极大值
#define MVNum 100 // 最大顶点数
bool visited[MVNum]; // 访问标志数组,其初值为 “false”
typedef char VerTexType; // 假设顶点的数据类型为字符型
typedef int ArcType; // 假设边的权值类型为整型
typedef struct {
VerTexType vexs[MVNum]; // 顶点表
ArcType arcs[MVNum][MVNum]; // 邻接矩阵
int vexnum, arcnum; // 图的当前点数和边数
} AMGraph;
int LocateVex(AMGraph G, VerTexType u) {
/* 存在则返回 u 在顶点表中的下标;否则返回 -1 */
for (int i = 0; i < G.vexnum; i++)
if (u == G.vexs[i])
return i;
return -1;
}
/* ————采用邻接矩阵表示法创建无向网 ————*/
Status CreateUDN(AMGraph &G) {
int i, j, k;
char flag;
ArcType w;
VerTexType v1, v2;
cout << "请选择图的类型(a - 无向图, b - 有向图):";
cin >> flag;
cout << "请输入总顶点数,总边数:";
cin >> G.vexnum >> G.arcnum; // 输入总顶点数,总边数
cout << "请依次输入点的信息:";
for (i = 0; i < G.vexnum; i++) // 依次输入点的信息
cin >> G.vexs[i];
for (i = 0; i < G.vexnum; i++) // 初始化邻接矩阵,边的权值均置为极大值 MaxInt
for (j = 0; j < G.vexnum; j++)
G.arcs[i][j] = MaxInt;
cout << "输入一条边依附的顶点及权值 (eg: a b 6): " << endl;
for (k = 0; k < G.arcnum; k++) { // 构造邻接矩阵
cin >> v1 >> v2 >> w; // 输入一条边依附的顶点及权值
i = LocateVex(G, v1); j = LocateVex(G, v2); // 确定 v1 和 v2 在 G 中的位置,即顶点数组的下标
G.arcs[i][j] = w; // 边 <v1, v2> 的权值为 w
if (flag == 'a')
G.arcs[j][i] = G.arcs[i][j]; // 置 <v1, v2> 的对称边 <v2, v1> 的权值为 w
}
return OK;
}
/* 返回顶点v的第一个邻接顶点序号 */
int FirstAdjVex(AMGraph G, int v) {
for(int i = 0; i < G.vexnum; i++)
if(G.arcs[v][i] == 1)
return i;
return -1;
}
/* 返回顶点v的相对于w的下一个邻接顶点序号 */
int NextAdjVex(AMGraph G, int v, int w) {
for(int i = w + 1; i < G.vexnum; i++)
if(G.arcs[v][i] == 1)
return i;
return -1;
}
void DFS(AMGraph G, int v) {
visited[v]=true;
cout<<G.vexs[v]<<" ";
for(int w=FirstAdjVex(G, v); w>=0; w=NextAdjVex(G, v, w))
if(!visited[w])
DFS(G, w);
}
/* 深搜 */
void DFSTraverse(AMGraph G) {
for(int i = 0; i < G.vexnum; i++)
visited[i] = false;
for(int i = 0; i < G.vexnum; i++)
if(!visited[i])
DFS(G, i);
}
/* 广搜,类似于树的层次遍历 */
void BFSTraverse(AMGraph G) {
for(int i = 0; i < G.vexnum; i++)
visited[i] = false;
queue<int> q;
for(int i = 0; i < G.vexnum; i++) {
if(!visited[i]) {
visited[i] = true;
q.push(i);
while(!q.empty()) {
int v = q.front();
q.pop();
cout << G.vexs[v] << " ";
for(int w = FirstAdjVex(G, v); w >= 0; w = NextAdjVex(G, v, w)) {
if(!visited[w]) {
visited[w] = true;
q.push(w);
}
}
}
}
}
}
int main() {
AMGraph G;
CreateUDN(G);
cout << "打印邻接矩阵:" << endl;
for (int i = 0; i < G.vexnum; i++) {
for (int j = 0; j < G.vexnum; j++) {
if (G.arcs[i][j] != MaxInt)
cout << G.arcs[i][j] << " ";
else cout << '0' << " ";
}
cout << endl;
}
int flag;
cout << "请选择遍历方式(1.深度优先搜索; 2.广度优先搜索):\n";
cin >> flag;
switch(flag) {
case 1:
cout << "DFS:";
DFSTraverse(G);
cout << endl;
break;
case 2:
cout << "BFS:";
BFSTraverse(G);
cout << endl;
}
return 0;
}
邻接表实现如下:
/*
主题:用邻接表实现 DFS(递归) 与 BFS(非递归)
作者:Laugh
语言:C++
*******************************************
样例输出如下:
请输入顶点数和边数:8 9
请输入顶点:v1 v2 v3 v4 v5 v6 v7 v8
请输入边:
v1 v2
v1 v3
v2 v4
v2 v5
v4 v8
v5 v8
v3 v6
v3 v7
v6 v7
打印邻接表如下:
v1->v3->v2
v2->v5->v4->v1
v3->v7->v6->v1
v4->v8->v2
v5->v8->v2
v6->v7->v3
v7->v6->v3
v8->v5->v4
请选择遍历方式(1.深度优先搜索; 2.广度优先搜索):1
DFS:v1 v3 v7 v6 v2 v5 v8 v4
BFS: v1 v3 v2 v7 v6 v5 v4 v8
*/
#include <iostream>
#include <string>
#include <queue>
using namespace std;
bool visited[10];
/* 表结点 */
typedef struct ArcNode {
int adjvex; // 该弧所指向的顶点的位置
ArcNode *nextarc; // 指向下一条弧的指针
} ArcNode;
/* 头结点 */
typedef struct VNode {
string data; // 顶点信息
ArcNode* firstarc; // 第一个表结点的地址,指向第一条依附该顶点的弧的指针
} VNode, AdjList[10];
typedef struct {
AdjList vertices;
int vexnum, arcnum; // 图的顶点数和弧数
} ALGraph;
/* 返回顶点u在图中的位置 */
int LocateVex(ALGraph G, string u) {
for(int i = 0; i < G.vexnum; i++)
if(G.vertices[i].data == u)
return i;
return -1;
}
/* 构造无向图 */
void CreateUDG(ALGraph &G) {
string v1, v2;
int i, j, k;
cout << "请输入顶点数和边数:";
cin >> G.vexnum >> G.arcnum;
cout << "请输入顶点:";
for(i = 0; i < G.vexnum; i++) {
cin >> G.vertices[i].data;
G.vertices[i].firstarc = NULL;
}
cout << "请输入边:";
cout << endl;
for(k = 0; k < G.arcnum; k++) {
cin >> v1 >> v2;
i = LocateVex(G, v1);
j = LocateVex(G, v2);
/* 插入v1的邻接表,为了提高效率,总在表头插入结点 */
ArcNode *arc = new ArcNode;
arc->adjvex = j;
arc->nextarc = G.vertices[i].firstarc;
G.vertices[i].firstarc = arc;
/* 插入v2的邻接表,为了提高效率,总在表头插入结点 */
arc = new ArcNode;
arc->adjvex = i;
arc->nextarc = G.vertices[j].firstarc;
G.vertices[j].firstarc = arc;
}
}
/* 打印邻接表 */
void Print(ALGraph G) {
cout<<"打印邻接表如下:" << endl;
/* 遍历每个顶点的邻接表 */
for(int i = 0; i < G.vexnum; i++) {
cout << G.vertices[i].data;
ArcNode *p = G.vertices[i].firstarc;
while(p) {
cout << "->" << G.vertices[p->adjvex].data;
p = p->nextarc;
}
cout<<endl;
}
}
/* 返回顶点v的第一个邻接点序号 */
int FirstAdjVex(ALGraph G, int v) {
ArcNode *p=G.vertices[v].firstarc;
if(p)
return p->adjvex;
else
return -1;
}
/* 返回顶点v的相对于w的下一个邻接点序号 */
int NextAdjVex(ALGraph G, int v, int w) {
ArcNode* p = G.vertices[v].firstarc;
while(p) {
if(p->adjvex == w)
break;
p = p->nextarc;
}
if(p->adjvex != w || !p->nextarc)//如果没找到w或者w是最后一个邻接点
return -1;
return p->nextarc->adjvex;
}
void DFS(ALGraph G, int v) {
visited[v] = true;
cout << G.vertices[v].data << " ";
for(int w = FirstAdjVex(G, v); w >= 0; w = NextAdjVex(G, v, w))
if(!visited[w])
DFS(G, w);
}
void DFSTraverse(ALGraph G) {
for(int i = 0; i < G.vexnum; i++)
visited[i] = false;
for(int i = 0; i < G.vexnum; i++)
if(!visited[i])
DFS(G, i);
}
void BFSTraverse(ALGraph G) {
queue<int> q;
for(int i = 0; i < G.vexnum; i++)
visited[i] = false;
for(int i = 0; i < G.vexnum; i++) {
if(!visited[i]) {
q.push(i);
visited[i] = true;
while(!q.empty()) {
int v = q.front();
q.pop();
cout << G.vertices[v].data << " ";
for(int w = FirstAdjVex(G, v); w >= 0; w = NextAdjVex(G, v, w)) {
if (!visited[w]) {
q.push(w);
visited[w] = true;
}
}
}
}
}
}
int main()
{
ALGraph G;
CreateUDG(G);
Print(G);
int flag;
cout << "请选择遍历方式(1.深度优先搜索; 2.广度优先搜索):\n";
cin >> flag;
switch(flag) {
case 1:
cout << "DFS:";
DFSTraverse(G);
cout << endl;
break;
case 2:
cout << "BFS:";
BFSTraverse(G);
cout << endl;
}
return 0;
}
【数据结构】图的基本操作——图的构造(邻接矩阵,邻接表),遍历(DFS,BFS)的更多相关文章
- 数据结构学习笔记05图 (邻接矩阵 邻接表-->BFS DFS、最短路径)
数据结构之图 图(Graph) 包含 一组顶点:通常用V (Vertex) 表示顶点集合 一组边:通常用E (Edge) 表示边的集合 边是顶点对:(v, w) ∈E ,其中v, w ∈ V 有向边& ...
- PAT1013. Battle Over Cities(邻接矩阵、邻接表分别dfs)
//采用不同的图存储结构结构邻接矩阵.邻接表分别dfs,我想我是寂寞了吧,应该试试并查集,看见可以用并查集的就用dfs,bfs代替......怕了并查集了 //邻接矩阵dfs #include< ...
- 第6章 图的学习总结(邻接矩阵&邻接表)
我觉得图这一章的学习内容更有难度,其实图可以说是树结构更为普通的表现形式,它的每个元素都可以与多个元素之间相关联,所以结构比树更复杂,然而越复杂的数据结构在现实中用途就越大了,功能与用途密切联系,所以 ...
- 图的数据结构的实现与遍历(DFS,BFS)
//图的存储结构:const int MAXSIZE = 10;//邻接矩阵template<class T>class MGraph {public: MGraph(T a[], ...
- 图的全部实现(邻接矩阵 邻接表 BFS DFS 最小生成树 最短路径等)
1 /** 2 * C: Dijkstra算法获取最短路径(邻接矩阵) 3 * 6 */ 7 8 #include <stdio.h> 9 #include <stdlib.h> ...
- JAVA实现图的邻接表以及DFS
一:定义邻接表结构储存图 package 图的遍历; //邻接表实现图的建立 //储存边 class EdgeNode { int index; // 习惯了用index,其实标准写法是(adjVer ...
- <图论入门>邻接矩阵+邻接表
非本人允许请勿转载. 趁热打铁,学会了邻接表把这个总结一下,以及感谢大佬uncle-lu!!!(奶一波)祝早日进队! 首先,图论入门就得是非常基础的东西,先考虑怎么把这个图读进去. 给定一个无向图,如 ...
- 网络流三大算法【邻接矩阵+邻接表】POJ1273
网络流的基本概念跟算法原理我是在以下两篇博客里看懂的,写的非常好. http://www.cnblogs.com/ZJUT-jiangnan/p/3632525.html http://www.cnb ...
- HDU 1874 畅通工程续(最短路/spfa Dijkstra 邻接矩阵+邻接表)
题目链接: 传送门 畅通工程续 Time Limit: 1000MS Memory Limit: 65536K Description 某省自从实行了很多年的畅通工程计划后,终于修建了很多路. ...
随机推荐
- Nginx平滑升级版本
目录 一.简介 说明 环境 二.安装 三.使用验证 一.简介 说明 Nginx版本迭代迅速,新版本提供了很多功能,好在Nginx支持不停服务进行升级. 版本之间差距不要太大,不然会导致很多东西不支持 ...
- [BUUCTF]REVERSE——[GWCTF 2019]pyre
[GWCTF 2019]pyre 附件 步骤: 1.附件是pyc文件,用python打不开,百度后得知用python反编译工具打开,分享一个python反编译在线网站 反编译后是这段代码 #!/usr ...
- SSM——Spring框架
Spring概念 什么是Spring Spring两大核心 1.IOC 所谓的IOC称之为控制反转,简单来说就是将对象的创建的权利及对象的生命周期的管理过程交由Spring框架来处理,从此在开发过程中 ...
- Libevent使用例子
初等: 客户端代码: #include<sys/types.h> #include<sys/socket.h> #include<netinet/in.h> #in ...
- element UI遇到的问题
1. 在el-dialog中获取el-table的ref为undefined 问题:虽然设置了el-dialog的visible为true,但此时Dom并没有更新,因此在Dom更新前取不到el-tab ...
- 『与善仁』Appium基础 — 29、获取toast信息
目录 1.toast介绍 2.toast定位 3.示例 4.封装toast判断 1.toast介绍 Android中的toast是一种简易的消息提示框,toast提示框不能被用户点击,会根据所设置的显 ...
- 【LeetCode】221. Maximal Square 解题报告(Python & C++)
作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 动态规划 日期 题目地址: https://leet ...
- VMware15 虚拟机分别设置连接笔记本的WLAN和以太网双网络
VMware15 虚拟机分别设置连接笔记本的WLAN和以太网双网络 虚拟机:window 10 主机: window 10 VVmware有3种网络连接模式:桥接.NAT.主机模式,默认分别对应VMN ...
- 快速恢复update了的orcale数据表
在update的时候 没有写条件 将整个表中的数据全部都更新了,这时候怎么办呢? orcale提供了以下的方法产看某一个时间戳, 所执行的sql的语句内容, 同时可以利用该这个时间戳查看当时语句执行显 ...
- 【操作系统】 DOS命令windows批处理batch编程——第一章
参考网址: http://docs.30c.org/dosbat/index.html 很多情况下,我们只需要记住一条命令 help ,就能掌握整个DOS命令.比如直接输入 help 可以得到命令的帮 ...