图的创建和遍历(BFS/DFS)
图的表示方法主要有邻接矩阵和邻接表。其中邻接表最为常用,因此这里便以邻接表为例介绍一下图的创建及遍历方法。
创建图用到的结构有两种:顶点及弧
struct ArcNode
{
int vertexIndex; //该弧指向的顶点位置
struct ArcNode* next; //指向下一个弧
InfoType info; //该弧的相关信息,如权重等
}; struct Vertex
{
VertexType data; //顶点信息
ArcNode* firstArc; //指向第一条依附该节点弧的指针
ColorType color; //访问情况
};
其中ColorType是一个枚举,遍历的时候才会用到。图的创建比较简单,直接看代码很容易理解,这里不再详细说了。 图的深度和广度遍历直接看算法导论中的两张图就明白了 :
//结点颜色代表遍历情况
enum ColorType
{
WHITE, //未访问
GRAY, //正在访问,邻接点还没访问完
BLACK //访问完毕
};
代码:
#include <queue>
#include <stack>
#include <iostream>
using namespace std; enum GraphType
{
UNDIR_UNWEIGHT_GRAPH, //无向无权图
UNDIR_WEIGHT_GRAPH, //无向带权图
DIR_UNWEIGHT_GRAPH, //有向无权图
DIR_WEIGHT_GRAPH //有向带权图
}; //结点颜色代表遍历情况
enum ColorType
{
WHITE, //未访问
GRAY, //正在访问,邻接点还没访问完
BLACK //访问完毕
}; template<typename VertexType,typename InfoType>
class Graph
{
public:
Graph(int vertexNum, GraphType type) :m_vertexNum(vertexNum), m_type(type), m_arcNum()
{
for (int i = ; i < MAX_VERTEX_NUM; ++i)
{
m_vertices[i].firstArc = nullptr;
}
} void Create()
{
switch (m_type)
{
case UNDIR_UNWEIGHT_GRAPH:
CreateUndirUnweightGraph();
break;
case UNDIR_WEIGHT_GRAPH:
CreateUndirWeightGraph();
break;
case DIR_UNWEIGHT_GRAPH:
CreateDirUnweightGraph();
break;
case DIR_WEIGHT_GRAPH:
CreateDirWeightGraph();
break;
default:
break;
}
} //输出图的信息
void Display()
{
for (int i = ; i < m_vertexNum; ++i)
{
cout << "第" << i + << "个结点为" << m_vertices[i].data << " 邻接表为:";
ArcNode* node = m_vertices[i].firstArc;
while (node)
{
cout << "->" << m_vertices[node->vertexIndex].data << "(" << node->info << ")";
node = node->next;
}
cout << endl;
}
} void BFS()
{
for (int i = ; i < m_vertexNum; ++i)
{
m_vertices[i].color = WHITE;
}
cout << "图的广度优先遍历为:";
BFS(&m_vertices[]);
cout << endl;
} void DFS()
{
for (int i = ; i < m_vertexNum; ++i)
{
m_vertices[i].color = WHITE;
}
cout << "图的深度优先遍历为:";
DFS(&m_vertices[]);
cout << endl;
}
private:
struct ArcNode
{
int vertexIndex; //该弧指向的顶点位置
struct ArcNode* next; //指向下一个弧
InfoType info; //该弧的相关信息,如权重等
}; struct Vertex
{
VertexType data; //顶点信息
ArcNode* firstArc; //指向第一条依附该节点弧的指针
ColorType color; //访问情况
}; //最大顶点数
static const int MAX_VERTEX_NUM = ;
Vertex m_vertices[MAX_VERTEX_NUM]; //顶点列表
int m_vertexNum; //当前顶点数量
int m_arcNum; //当前弧数量
GraphType m_type; //图类型:有向无权图、有向带权图、无向无权图、无向无权图
private:
//初始化顶点列表
void InitVertices()
{
cout << "请输入每个顶点的关键字" << endl;
VertexType data;
for (int i = ; i < m_vertexNum; ++i)
{
cin >> data;
m_vertices[i].data = data;
}
}
//插入一个表结点
void Insert(int headVertex, int tailVertex, InfoType info)
{
//构造一个邻接表结点,即创建一条弧
ArcNode* newNode = new ArcNode;
newNode->info = info;
newNode->next = nullptr;
newNode->vertexIndex = tailVertex; //找到邻接表的最后一个节点
ArcNode* lastNode = m_vertices[headVertex].firstArc;
if (lastNode == nullptr)
m_vertices[headVertex].firstArc = newNode;
else
{
while (lastNode->next)
{
lastNode = lastNode->next;
}
lastNode->next = newNode;
}
++m_arcNum;
} //创建无向无权图
void CreateUndirUnweightGraph()
{
InitVertices();
cout << "请分别输入每条边的起始结点:" << endl;
int head, tail;
while (cin >> head >> tail)
{
//无向图head->tail tail->head插入两次
Insert(head, tail, );
Insert(tail, head, );
}
}
//创建无向有权图
void CreateUndirWeightGraph()
{
InitVertices();
cout << "请分别输入每条边的起始结点和权值:" << endl;
int head, tail;
InfoType weight;
while (cin >> head >> tail >> weight)
{
Insert(head, tail, weight);
Insert(tail, head, weight);
}
}
//创建有向无权图
void CreateDirUnweightGraph()
{
InitVertices();
cout << "请分别输入每条边的起始结点值:" << endl;
int head, tail;
while (cin >> head >> tail)
{
Insert(head, tail,);
}
}
//创建有向带权图
void CreateDirWeightGraph()
{
InitVertices();
cout << "请分别输入每条边的起始结点和权值:" << endl;
int head, tail;
InfoType weight;
while (cin >> head >> tail >> weight)
{
Insert(head, tail, weight);
}
} void BFS(Vertex* vertex)
{
vertex->color = GRAY;
queue<Vertex*> vertices;
vertices.push(vertex);
while (!vertices.empty())
{
Vertex* curVertex = vertices.front();
vertices.pop();
cout << curVertex->data << "->";
ArcNode* node = curVertex->firstArc;
while (node)
{
Vertex* tmpVertex = &m_vertices[node->vertexIndex];
if (tmpVertex->color == WHITE)
{
tmpVertex->color = GRAY;
vertices.push(tmpVertex);
}
node = node->next;
}
curVertex->color = BLACK;
}
} void DFS(Vertex* vertex)
{
vertex->color = GRAY;
stack<Vertex*> vertices;
vertices.push(vertex);
while (!vertices.empty())
{
Vertex* curVertex = vertices.top();
vertices.pop();
cout << curVertex->data << "->";
ArcNode* node = curVertex->firstArc;
while (node)
{
Vertex* tmp = &m_vertices[node->vertexIndex];
if (tmp->color == WHITE)
{
tmp->color = GRAY;
vertices.push(tmp);
}
node = node->next;
}
curVertex->color = BLACK;
}
}
}; int main()
{
int vertexNum;
cout << "请输入要创建的图的结点数:";
cin >> vertexNum;
Graph<char, int> g(vertexNum,GraphType::UNDIR_UNWEIGHT_GRAPH);
g.Create();
g.Display();
g.BFS();
g.DFS();
}
运行结果:(创建的树为算法导论BFS说明图片中的树)
图的创建和遍历(BFS/DFS)的更多相关文章
- 【算法导论】图的深度优先搜索遍历(DFS)
关于图的存储在上一篇文章中已经讲述,在这里不在赘述.下面我们介绍图的深度优先搜索遍历(DFS). 深度优先搜索遍历实在访问了顶点vi后,访问vi的一个邻接点vj:访问vj之后,又访问vj的一个邻接点, ...
- JS实现图的创建和遍历
图分为无向图和有向图 图的存储结构有邻接矩阵.邻接表.十字链表.邻接多重表这四种,最常用的是前两种 本篇主要是利用邻接矩阵实现无向图的创建和遍历(深度优先.广度优先),深度优先其实就是二叉树里的前序遍 ...
- 图的两种遍历:DFS&BFS
DFS和BFS在图中的应用: 图连通性判定:路径的存在性:图中是否存在环:求图的最小生成树:求图的关键路径:求图的拓扑排序. DFS:简单的说,先一直往深处走,直到不能再深了,再从另一条路开始往深处走 ...
- 模板 图的遍历 bfs+dfs 图的最短路径 Floyed+Dijkstra
广搜 bfs //bfs #include<iostream> #include<cstdio> using namespace std; ],top=,end=; ][]; ...
- 图的广度优先/层次 遍历(BFS) c++ 队列实现
在之前的博文中,介绍了图的深度优先遍历,并分别进行了递归和非递归实现.BFS 无法递归实现,最广泛的实现是利用队列(queue).这与DFS的栈实现是极其相似的,甚至代码几乎都很少需要改动.从给定的起 ...
- 算法导论—无向图的遍历(BFS+DFS,MATLAB)
华电北风吹 天津大学认知计算与应用重点实验室 最后改动日期:2015/8/22 无向图的存储方式有邻接矩阵,邻接链表,稀疏矩阵等. 无向图主要包括双方面内容,图的遍历和寻找联通分量. 一.无向图的遍历 ...
- 数据结构(三十二)图的遍历(DFS、BFS)
图的遍历和树的遍历类似.图的遍历是指从图中的某个顶点出发,对图中的所有顶点访问且仅访问一次的过程.通常有两种遍历次序方案:深度优先遍历和广度优先遍历. 一.深度优先遍历 深度优先遍历(Depth_Fi ...
- 图的深度优先遍历(DFS)和广度优先遍历(BFS)
body, table{font-family: 微软雅黑; font-size: 13.5pt} table{border-collapse: collapse; border: solid gra ...
- 数据结构作业——图的存储及遍历(邻接矩阵、邻接表+DFS递归、非递归+BFS)
邻接矩阵存图 /* * @Author: WZY * @School: HPU * @Date: 2018-11-02 18:35:27 * @Last Modified by: WZY * @Las ...
随机推荐
- Java NIO实战之聊天室
在工作之余花了两个星期看完了<Java NIO>.整体来说这本书把NIO写的非常具体,没有过多的废话,讲的都是重点,仅仅是翻译的中文版看的确实吃力.英文水平太低也没办法,总算也坚持看完了. ...
- Button UI Kit CSS3美丽Buttonbutton
<!DOCTYPE HTML> <html lang="en-US"> <head> <meta charset="UTF-8& ...
- shodan
https://www.shodan.io/ from:http://www.exploit-db.com/wp-content/themes/exploit/docs/33859.pdf 0x00 ...
- HP MSA2312 ERROR
司在用的hp MAS2312存储其中一台每天都会报一个错误 EVENT:Vdisk verification failed. Command failed. (error code: 1) 2 err ...
- Windows8和MacOS10.9双系统安装及Mac经常使用软件安装--联想E49A
前提 本篇内容所描写叙述的内容仅仅适合联想E49A笔记本,经过本篇的内容之后,对于Mac OS 10.9的使用达到正常工作使用的标准,完美度已经比較好了. 结果例如以下:显卡.网卡(RTL8168). ...
- linux内存基础知识和相关调优方案
内存是计算机中重要的部件之中的一个.它是与CPU进行沟通的桥梁. 计算机中全部程序的执行都是在内存中进行的.因此内存的性能对计算机的影响很大.内存作用是用于临时存放CPU中的运算数据,以及与硬盘等外部 ...
- Java Swing界面编程(28)---复选框:JCheckBox
程序能够通过JRadioButton实现单选button的功能,那么要实现复选框的功能,则必须使用JCheckBox完毕. package com.beyole.util; import java.a ...
- 智能手机的工业控制应用方案——SimpleWiFi在工业控制领域应用
智能手机的工业控制应用方案——SimpleWiFi在工业控制领域应用 先上图: 现在的智能控制都是基于微控制器,随着智能的手持终端的普及,基于智能终端的控制就会越来越普遍. WIFI便是其中的一 ...
- Visual Leak Detector(vld)无法显示内存泄露文件名称与行号
使用VLD測有没内存泄露的时候,出现(File and line number not available): (Function name unavailable) 查看VS控制台,发现 已载入&q ...
- poj 动态规划的主题列表和总结
此文转载别人,希望自己可以做完这些题目. 1.POJ动态规划题目列表 easy:1018, 1050, 1083, 1088, 1125, 1143, 1157, 1163, 1178, 1179, ...