图的创建和遍历(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 ...
随机推荐
- Apache htaccess 重写假设文件存在!
假设文件 data/cache/index.html 存在.那么才重写. 否则使用默认的MVC 重写.by default.fu@foxmail.com RewriteEngine on Rewrit ...
- ESP8266学习笔记1:怎样在安信可全功能測试板上实现ESP-01的编译下载和调试
近期调试用到了安信可的ESP-01模块,最终打通了编译下载调试的整个通道,有一些细节须要记录,方便兴许的开发工作. 转载请注明:http://blog.csdn.net/sadshen/article ...
- DelphiXE7中创建WebService(服务端+客户端) good
相关资料:http://www.2ccc.com/news/Html/?1507.html DelphiXE7新建WebService具体操作:1.打开“DelphiXE7”->“File”-& ...
- [Android学习笔记]Bitmap,BitmapDrawable,BitmapFactory学习笔记
Bitmap:图片文件的封装,可以看做是一张位图此类中的静态方法可以通过源Bitmap创建新的Bitmap对象此类封装了位图的一些信息Bitmap文档 BitmapFactory:一个工具类,用于创建 ...
- 那些年我们装过的数据库---盘点sqlserver2008安装时遇到的各种的问题(持续更新中)
给自己安过sqlServer2008,也给好多同学安过sqlServer2008,期间遇到了好多不同的另人心烦的问题,在这里整理一下,(涉及到的部分方法是在网上找的,有些也没试过,仅仅是在这里整理一下 ...
- Android 实现自己定义多级树控件和全选与反选的效果
博文開始之前,首先要感谢大牛:(lmj623565791),本博文是在其博文http://blog.csdn.net/lmj623565791/article/details/40212367基础上进 ...
- Eclipse乱码怎么办
Eclipse里设置编码有三个层次:全局.工程.文件. 文件的编码会覆盖工程的编码,工程的编码会覆盖全局的编码. 我猜测:虽然你的工程编码更改为GBK,但只对新建文件有效. 如果工程中旧有的文件是UT ...
- 网页favicon.ico图标设置(转)
随便打开一个网页:比如 http://www.baidu.com/ 可以看到在浏览器的标签头上面显示了一个图标,这个图标是:,也就是我们常说的favicon.ico. 由于这篇文章主要讨论favico ...
- Android 程序静态分析
简介 静态分析是探索Android程序内幕的一种最常见的方法,它与动态调剂双剑合璧,帮助分析人员解决分析时遇到的各种“疑难”问题. 静态分析是指在不运行的情况下,采用词法分析.语法分析等各种技术手段对 ...
- NGUI使用教程(3) 使用外部图片制作Atlas(图集)
在实际操作之前有几个概念先弄清一下 Atlas:图集,把美术给你提供的素材,用 NGUI 的 Atlas Maker 工具.合成一张图片(准确的说,还同一时候生成了prefab.mat ). Spri ...
