图的创建和遍历(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 ...
随机推荐
- 使用KnockoutJs+Bootstrap实现分页
[后端人员耍前端系列]KnockoutJs篇:使用KnockoutJs+Bootstrap实现分页 一.引言 由于最近公司的系统需要改版,改版的新系统我打算使用KnockoutJs来制作Web前端 ...
- VMware中linux与window目录共享
在虚拟机下来实如今windows下共享一个目录: (前提已安装完毕vmtools:http://blog.csdn.net/pipisorry/article/details/21318931) 打开 ...
- 阿尔贝我给我加i觉
http://www.huihui.cn/share/8192186 http://www.huihui.cn/share/8192178 http://www.huihui. ...
- hdu2036 (计算多边形的面积)
Input 输入数据包含多个测试实例,每个测试实例占一行,每行的开始是一个整数n(3<=n<=100),它表示多边形的边数(当然也是顶点数),然后是按照逆时针顺序给出的n个顶点的坐标(x1 ...
- evnetlet hub
hub 是 Eventlet's event loop的主要部分,用于分配I/O 事件 和调度绿色线程. Eventlet 有多种hub实现,现支持一下几种: epoll poll selects p ...
- Thinkphp中field和getField
在数据库查询操作中field和getField方法是使用最频繁的.可是两者是有一定差别的.在这里记录下. field方法是用于定义要查询的字段(支持字段排除). getField方法获取数据表中的某个 ...
- auto property synthesis will not synthesize proterty ;it will be implementedby its superclass, use @
Auto property synthesis will not synthesize property 'title'; it will be implemented by its supercla ...
- H264 编解码框架简单介绍
阅读完H264/AVC 编解码器的介绍,脑海中仅仅是留下下面三条: 1.H264并没有明白规定一个编解码器怎样实现,仅仅是规定了一个编码后的视频比特流的句法,和该比特流的解码方法,这个与MPEG 类似 ...
- iOS 通讯录-获取联系人属性
内容均来自关东升老师的ios开发指南 上一篇写了联系人框架的一些必须知道的知识 如今写一下读取联系人数据相关操作 要读取通讯录数据库 须要 创建通讯录对象 查询获取数据(全部或者部分) 获取通讯录某一 ...
- Akka边学边写(3)-- ByteString介绍
Akka的IO层设计能够參考这篇文档,本文简介一下ByteString的设计. Immutable消息 Actor之间是通过消息沟通的.但为了避免同步问题,消息必须是Immutable. 因此.Akk ...