数据结构之图(邻接表存储,DFS和BFS遍历)
来源:互联网 发布:top gear 知乎 编辑:程序博客网 时间:2024/06/05 05:05
来看下面的一个简单的图,
那么这样的一个图,我们应该用什么存储结构来存储它呢?常用的是邻接矩阵和邻接表,这里邻接矩阵不做讲解,如下所有代码都是以邻接表作为存储结构,所以这里就只讲解下邻接表。那么什么是邻接表呢?如何构造呢?
邻接表是一种链式存储。就如上图,一共有四个顶点(分别是A,B,C,D),邻接表就是为这四个顶点的每个顶点建立一条单链表,也就是四条单链表,每个链表第一个元素就是该顶点自己。下面就以上面的图为例,具体介绍如何建立邻接表。
首先看第一条单链表,表头是顶点A。因为顶点A只与顶点B有邻接,因此,该单链表大概描述为A---->B;
再看第二条单链表,表头是B,而B与A,C,D都有邻接,故而描述为B----->A------->C------->D;
依次第三条单链表为C------>B----->D;
最后第四条单链表为D------>B----->C。
现在来理清一下下面代码的三个结构体都代表什么,理清的话,下面的代码就很容易理解了。
struct ArcNode{int adjvex; //该弧所指向的顶点的位置ArcNode * next; //指向下一条弧的指针 //int weight;边上是否有权};typedef struct VNode{char vertex; //顶点信息ArcNode * firstarc; //指向第一条依附该顶点的弧的指针 }AdjList[20];struct ALGraph{AdjList adjList;int vexNum; //图的顶点数int arcNum; //图的弧数};
看第二个结构体VNode,上面已经说过,对于ABCD四个顶点每个建立一条单链表,那么这四条链表该如何管理呢?对的,用数组,这也就是AdjList[20]的由来(这里假设一个图的顶点不超过20个,读者可以根据自己需求改动)。
第一个结构体ArcNode就是建立链表所必需的节点。
那么最后一个结构体ALGraph就是用来表示一个图,在一段程序里,你要做三个图,就要用这个结构体去申请三个变量,来存储你的三个图。
好了,接下来直接看代码吧。所有源码都已经在下面贴出,没有遗漏。以下代码创建的图是无向,无权图,并且使用邻接表表示图。部分代码参考严蔚敏的数据结构。
一:main部分
#include<iostream>#include<queue>using namespace std;struct ArcNode{int adjvex; //该弧所指向的顶点的位置ArcNode * next; //指向下一条弧的指针 //int weight;边上是否有权};typedef struct VNode{char vertex; //顶点信息ArcNode * firstarc; //指向第一条依附该顶点的弧的指针 }AdjList[20];struct ALGraph{AdjList adjList;int vexNum; //图的顶点数int arcNum; //图的弧数};bool visited[20];//设置标志数组void CreateGraph(ALGraph & graph);void PrintGraph(ALGraph & graph);void DFSTraverse(ALGraph & graph);void BFSTraverse(ALGraph & graph);int main(){/*89A B C D E F G H0 10 21 31 42 52 63 74 75 6*/ALGraph graph;//1.创建邻接表CreateGraph(graph);//2.打印邻接表cout << "\n邻接表打印为: \n";PrintGraph(graph);//3.深度优先搜索DFScout << "\n深度优先搜索DFS: ";DFSTraverse(graph);cout << endl;//4.广度优先搜索BFScout << "\n广度优先搜索BFS: ";BFSTraverse(graph);cout << endl<<endl;return 0;}
二:具体实现
1.构造邻接表
void CreateGraph(ALGraph & graph){////////1.输入顶点数和弧数cout << "请输入图的顶点数: ";cin >> graph.vexNum;cout << "请输入图的弧数: ";cin >> graph.arcNum;///////2.输入顶点信息cout << "请输入" << graph.vexNum << "个顶点信息: ";for (int i = 0; i < graph.vexNum; i++){cin >> graph.adjList[i].vertex;graph.adjList[i].firstarc = nullptr;}///////3.根据输入的弧的信息构造邻接表cout << "请输入" << graph.arcNum << "个弧的信息: \n";int h1, h2;ArcNode * temp;for (int i = 0; i < graph.arcNum; i++){cin >> h1 >> h2;temp = new ArcNode;temp->adjvex = h2;temp->next = graph.adjList[h1].firstarc;graph.adjList[h1].firstarc = temp;temp = new ArcNode;temp->adjvex = h1;temp->next = graph.adjList[h2].firstarc;graph.adjList[h2].firstarc = temp;}}
2.打印邻接表
void PrintGraph(ALGraph & graph){for (int i = 0; i < graph.vexNum; i++){cout << graph.adjList[i].vertex << "------>";ArcNode * p = graph.adjList[i].firstarc;while (p){cout << graph.adjList[p->adjvex].vertex << " ";p = p->next;}cout << endl;}}
3.深度优先搜索DFS。类似于树的先序遍历。假设图中所有顶点未被访问,则深度优先遍历是从某个顶点v开始,访问完后,接着访问v的未被访问的邻接点,直至遍历完。
void DFS(ALGraph & graph, int v){visited[v] = true;cout << graph.adjList[v].vertex << " ";ArcNode * p = graph.adjList[v].firstarc;while (p){if (!visited[p->adjvex])DFS(graph, p->adjvex);p = p->next;}}void DFSTraverse(ALGraph & graph){for (int i = 0; i < graph.vexNum; i++)//初始化访问标志数组visited[i] = false;for (int i = 0; i < graph.vexNum; i++){if (!visited[i])//如果没有访问DFS(graph, i);}}
4.广度优先搜索BFS。类似于树的层次遍历。假设图中所有顶点未被访问,则广度优先遍历是从某个顶点v开始,访问后,接着访问v的未被访问的邻接点,然后分别从这些邻接点开始依次访问它们的邻接点(因此用到了队列),直至遍历完。
void BFSTraverse(ALGraph & graph){for (int i = 0; i < graph.vexNum; i++)//初始化访问标志数组 visited[i] = false;queue<int> q;for (int i = 0; i < graph.vexNum; i++){if (!visited[i])//如果没有访问过{visited[i] = true;q.push(i);//访问过的入队列cout << graph.adjList[i].vertex << " ";while (!q.empty())//队列不为空时{int x = q.front();q.pop();//先取出队首第一个元素,然后将第一个元素删除ArcNode * p = graph.adjList[x].firstarc;while (p)//访问未被访问过的邻接顶点{if (!visited[p->adjvex]){visited[p->adjvex] = true;cout << graph.adjList[p->adjvex].vertex << " ";q.push(p->adjvex);}p = p->next;}}}}}
三:数据测试
其中上述数据创建的图的结构如下图:
- 数据结构之图(邻接表存储,DFS和BFS遍历)
- 图的邻接表存储及DFS,BFS遍历
- 图的遍历--使用邻接表作为存储结构的遍历(DFS、BFS)C语言
- DFS BFS遍历图 邻接表实现
- 图的遍历(BFS、DFS的邻接矩阵和邻接表实现)
- 数据结构 学习笔记(七):图(上):图的表示方法(邻接表,邻接矩阵),遍历(DFS,BFS)
- 【数据结构】图的遍历之DFS和BFS
- 基于邻接表存储的图的DFS与BFS遍历
- 基于邻接表存储的图的DFS与BFS遍历
- 图的dfs递归(非递归)遍历和bfs遍历(邻接表)
- 邻接表实现--图的深度优先遍历DFS和广度优先遍历BFS
- 数据结构 — 图之邻接表存储创建和深度优先遍历
- 数据结构之图的遍历(BFS+DFS)
- 数据结构之无向图邻接表DFS之查询遍历关节点(参考整理严蔚敏数据结构)
- 邻接表深度优先和广度优先遍历(DFS和BFS)
- 数据结构之BFS(邻接表版)
- 图的BFS,DFS(邻接表)
- 图的邻接表和DFS遍历
- bash常用快捷键
- Tomcat启动
- [Python标准库]heapq——堆排序算法
- ./configure 命令详解
- 安装JDK过程中的一些注意事项
- 数据结构之图(邻接表存储,DFS和BFS遍历)
- iOS中单例模式的创建
- Python学习笔记 基础语法
- ITOO4.1之LocalStorage 本地存储
- 大数据的启蒙
- php rewrite模式
- 1193: [HNOI2006]马步距离
- Qt学习之路(10):自定义事件与事件控制的5大层次
- 什么是HTTP?Ping命令是什么?