涉及的知识点:
1. 邻接表的建立。
2. Breadth First Search:广度优先搜索,利用队列,使用类似于二叉树层次遍历的方法,将顶点V出队后将V的邻接点入队,重复上述过程,直至访问完所有的节点(队列为空)。
3.Depth First Search: 深度优先搜索,从顶点V出发一路走到黑,走不下去的时候利用回溯的思想原路返回,直到从起点V出发并且利用回溯法又一次回到了起点时,搜索完成。(递归实现)。
本题输入所对应的图:
话不多说,直接上代码:
//#pragma once /* 图的邻接表表示法 */ //DFS、BFS #include <iostream> #include <malloc.h> using namespace std; #define MaxVertexNum 50 /* 最大顶点数设为50 */ typedef int Vertex; /* 用顶点下标表示顶点,为整型 */ typedef int WeightType; /* 边的权值设为整型 */ typedef char DataType; /* 顶点存储的数据类型设为字符型 */ int Visited[MaxVertexNum]; //全局变量,用来表示节点是否被访问 typedef struct arcnode //边结构 { int adjvex; //下一条边的始点编号 struct arcnode* nextarc; //下一条边的指针 }; typedef struct vexnode //顶点数组 { Vertex vertex; //顶点编号 arcnode* firstarc; //边表头指针 }AdjList[MaxVertexNum]; //LGraph类定义 - 邻接表类定义-------- template <class T> class LGraph { private: int Nv; //顶点数 int Ne; //边数 AdjList adjlist; //邻接表所表示的图(指针数组) public: LGraph() { Nv = 0; Ne = 0; } //构造函数 ~LGraph(); //析构函数 bool BuildLGraph(); //根据用户输入建立一个图 void DFS(Vertex v); //从顶点v开始深度优先搜索 void BFS(Vertex v); //从顶点v开始广度优先搜索 void DispLGraph(); //输出由邻接表所表示的图 int GetNv() { return Nv; } //获取顶点数 }; //LGraph类的实现 template <class T> bool LGraph<T>::BuildLGraph() { int i, k, j; arcnode *p = NULL; cout << "--------创建一个由邻接表所表示的图---------" << endl; cout << "顶点数:"; cin >> Nv; cout << "边数:"; cin >> Ne; //初始化邻接表 for (i = 0; i < Nv; i++) { adjlist[i].vertex = i; adjlist[i].firstarc = NULL; } for (k = 0; k < Ne; k++) { cout << " 第" << k + 1 << "条边(节点号从0到" << Nv - 1 << "):"; cin >> i >> j; p = new arcnode; //创建边节点 //初始化边节点 p->adjvex = j; p->nextarc = NULL; //将边节点p插入到adjlist[i]链表的前面 p->nextarc = adjlist[i].firstarc; adjlist[i].firstarc = p; } } //DispLGraph() - 输出由邻接表所表示的图 template <class T> void LGraph<T>::DispLGraph() { cout << "------输出一个由邻接表所表示的图--------" << endl; int i, have; //have用来标记顶点V是否有邻接点 arcnode *p = NULL; for (i = 0; i < Nv; i++) { p = adjlist[i].firstarc; have = 0; while (p != NULL) { cout << " (" << i << ", " << p->adjvex << ")"; p = p->nextarc; have = 1; } if (have == 1) cout << endl; } } //~LGraph() - 析构函数 template <class T> LGraph<T>::~LGraph() { cout << "--------释放动态分配的存储空间----------" << endl; int i; arcnode *p = NULL, *tmp = NULL; for (i = 0; i < Nv; i++) { p = adjlist[i].firstarc; while (p != NULL) { tmp = p; p = p->nextarc; delete tmp; } } } //DFS(Vertex v) - 从顶点v开始深度优先搜索图g(回溯思想) template <class T> void LGraph<T>::DFS(Vertex v) { arcnode *p = NULL; cout << v << " "; //访问节点v Visited[v] = 1; //标记v节点已被访问 p = adjlist[v].firstarc; //p指向节点v的表头指针 while (p != NULL) { if (!Visited[p->adjvex]) //若v有邻接点 DFS(p->adjvex); //递归调用DFS p = p->nextarc; } } //BFS(Vertex v) - 从顶点v开始广度优先搜索图g(类似于树中的层次遍历) - 使用队列 template <class T> void LGraph<T>::BFS(Vertex v) { //定义队列 int queue[MaxVertexNum], rear = 0, first = 0; //rear - 队尾、first - 队头指针 int i; arcnode *p = NULL; //将节点标记清0 for (i = 0; i < Nv; i++) Visited[i] = 0; cout << v << " "; //访问节点v Visited[v] = 1; //标记节点v入队 queue[++rear] = v; //v入队列 while (rear != first) //队列不为空时 { v = queue[++first]; //队头节点出队 p = adjlist[v].firstarc; //找到队头节点所对应的表头指针 while (p != NULL) { if (!Visited[p->adjvex]) //若队头节点有邻接点,则再以邻接点为起点去找到该邻接点所对应的链表 { cout << p->adjvex << " "; //访问p Visited[p->adjvex] = 1; //添加标记 queue[++rear] = p->adjvex; //p入队 } p = p->nextarc; } } } void InitVisited(int num) { int i; //节点标记清0 for (i = 0; i < num; i++) Visited[i] = 0; } int main() { LGraph<int> lgraph; Vertex v; //指定的访问起点 lgraph.BuildLGraph(); //建立邻接表形式表示的图 lgraph.DispLGraph(); //输出该图 cout << "访问起点:"; cin >> v; //BFS - Breadth First Search cout << "BFS: "; int num = lgraph.GetNv(); //取得节点数 InitVisited(num); //访问标记清0 lgraph.BFS(v); cout << endl; //DFS - Depth First Search cout << "DFS:"; InitVisited(num); lgraph.DFS(v); cout << endl; return 0; }