图的遍历(下)——邻接表
来源:互联网 发布:欧奈尔选股公式源码 编辑:程序博客网 时间:2024/06/08 14:23
概述
在我的上一篇博客:图的遍历(上)——邻接矩阵 中主要介绍了邻接矩阵的BFS和递归的DFS与非递归的DFS这3种遍历算法。在这篇博客我将主要叙述邻接表的以上3中遍历算法。首先来看看邻接表的表示方法。
邻接表主要是针对稀疏图中邻接矩阵造成的空间浪费而提出的。下面我们来看看邻接表的表示。
1)无向图的表示
2)有向图
(说明:对于BFS,DFS的递归与非递归算法在这篇文章就不再重复,如有不了解请移步我的上一篇博客:图的遍历(上)——邻接矩阵 )
广度优先遍历(BFS)
//广度优先遍历(BFS)void BFS(int vertex){ EdgeList* cur = this->Find(vertex); //找到当前结点 queue<int> queue; //初始化队列 queue.push(cur->getVertex(cur)); //当前结点入队 while(!queue.empty()){ int index = queue.front(); //队头元素出队 queue.pop(); isvisited[index] = 1; //标记为已访问 cout<<index<<" "; cur = this->Find(index); while(cur){ //与当前结点相邻且未被访问的结点入队 index = cur->getVertex(cur); if(isvisited[index] == 0){ queue.push(index); } cur = cur->getNext(); } }}
递归深度优先遍历(DFS)
//递归深度优先遍历(DFS)void DFS1(int vertex){ vector<int> node; //找到当前结点 EdgeList* cur = this->Find(vertex); while(cur){ //寻找当前结点的邻接点 node.push_back(cur->getVertex(cur)); cur = cur->getNext(); } //打印当前结点 cur = this->Find(node[0]); int index = cur->getVertex(cur); this->isvisited[index] = 1; cout<<index<<" "; //一次堆当前结点的邻接点进行DFS for(int i = 1 ; i < node.size() ; i++){ cur = this->Find(node[i]); index = cur->getVertex(cur); if(this->isvisited[index] == 0){ this->isvisited[index] = 1; this->DFS1(index); } }}
非递归深度优先遍历(DFS)
//非递归深度优先遍历(DFS)void DFS2(int vertex){ stack<int> stack; EdgeList* cur = this->Find(vertex); //查找当前元素 int index = cur->getVertex(cur); //当前元素的顶点 stack.push(index); //顶点入栈 this->isvisited[index] = 1; //标记为已访问 while(!stack.empty()){ //栈不空一直循环 index = stack.top(); //栈顶的顶点出栈 stack.pop(); cout<<index<<" "; //打印当前顶点 cur = this->Find(index); while(cur){ //把当前顶点的邻接点依次入栈 index = cur->getVertex(cur); if(this->isvisited[index] == 0){ stack.push(index); this->isvisited[index] = 1; } cur = cur->getNext(); } }}
例子
下面的程序所基于的图结构够如下:
#include <iostream>#include <vector> #include <queue> #include <stack>#include <cstring> using namespace std;//边表类 class EdgeList{ private: int vertex; EdgeList* next; public: EdgeList* Create(int vertex){ EdgeList* list = new EdgeList; list->vertex = vertex; list->next = NULL; return list; } //寻找最后一个结点 EdgeList* getLast(EdgeList* list){ EdgeList* cur = list; while(cur){ if(cur->next == NULL){ return cur; } cur = cur->next; } } //插入函数 EdgeList* Attach(EdgeList* list,int vertex){ EdgeList* last = this->getLast(list); EdgeList* insert = insert->Create(vertex); last->next = insert; return list; } int getVertex(EdgeList* list){ return list->vertex; } void Print(EdgeList* list){ EdgeList* cur = list; while(cur){ cout<<cur->vertex<<" "; cur = cur->next; } } EdgeList* getNext(){ return this->next; }}; class Graph{ private: vector<EdgeList*> Edgelist; //邻接表 int* isvisited; //访问数组 int Nv; //顶点数 int Ne; //边数 public: //构造函数 Graph(int nv ,int ne){ this->Ne = ne; this->Nv = nv; this->Edgelist.reserve(nv); this->isvisited = new int[nv+1]; memset(this->isvisited,0,sizeof(this->isvisited[0])*(this->Nv+1)); cout<<"请输入顶点:"<<endl; //依次构造图的结点 for(int i = 0 ; i < this->Nv ; i++){ int vertex; cin>>vertex; this->Edgelist[i] = new EdgeList; this->Edgelist[i] = this->Edgelist[i]->Create(vertex); } cout<<"请输入边:"<<endl; //依次构造无向图的边 for(int i = 0 ; i < this->Ne ; i++){ int start,end; cin>>start>>end; //找到一条边的两个顶点 EdgeList* s1 = this->Find(start); EdgeList* s2 = this->Find(end); s1->Attach(s1,end); s2->Attach(s2,start); } } //按指定结点查找 EdgeList* Find(int vertex){ for(int i = 0 ; i < this->Nv ; i++){ if(this->Edgelist[i]->getVertex(this->Edgelist[i]) == vertex){ return this->Edgelist[i]; } } } //打印邻接表函数 void Print(){ for(int i = 0 ; i < this->Nv ; i++){ EdgeList* list = this->Edgelist[i]; list->Print(list); cout<<endl; } } //广度优先遍历(BFS) void BFS(int vertex){ EdgeList* cur = this->Find(vertex); //找到当前结点 queue<int> queue; //初始化队列 queue.push(cur->getVertex(cur)); //当前结点入队 while(!queue.empty()){ int index = queue.front(); //队头元素出队 queue.pop(); isvisited[index] = 1; //标记为已访问 cout<<index<<" "; cur = this->Find(index); while(cur){ //与当前结点相邻且未被访问的结点入队 index = cur->getVertex(cur); if(isvisited[index] == 0){ queue.push(index); } cur = cur->getNext(); } } } //重置访问数组 void reset(){ memset(this->isvisited,0,sizeof(this->isvisited[0])*(this->Nv+1)); } //递归深度优先遍历(DFS) void DFS1(int vertex){ vector<int> node; //找到当前结点 EdgeList* cur = this->Find(vertex); while(cur){ //寻找当前结点的邻接点 node.push_back(cur->getVertex(cur)); cur = cur->getNext(); } //打印当前结点 cur = this->Find(node[0]); int index = cur->getVertex(cur); this->isvisited[index] = 1; cout<<index<<" "; //一次堆当前结点的邻接点进行DFS for(int i = 1 ; i < node.size() ; i++){ cur = this->Find(node[i]); index = cur->getVertex(cur); if(this->isvisited[index] == 0){ this->isvisited[index] = 1; this->DFS1(index); } } } //非递归深度优先遍历(DFS) void DFS2(int vertex){ stack<int> stack; EdgeList* cur = this->Find(vertex); //查找当前元素 int index = cur->getVertex(cur); //当前元素的顶点 stack.push(index); //顶点入栈 this->isvisited[index] = 1; //标记为已访问 while(!stack.empty()){ //栈不空一直循环 index = stack.top(); //栈顶的顶点出栈 stack.pop(); cout<<index<<" "; //打印当前顶点 cur = this->Find(index); while(cur){ //把当前顶点的邻接点依次入栈 index = cur->getVertex(cur); if(this->isvisited[index] == 0){ stack.push(index); this->isvisited[index] = 1; } cur = cur->getNext(); } } } };int main(){ cout<<"请输入顶点数与边数:"<<endl; int nv,ne; cin>>nv>>ne; Graph graph(nv,ne); cout<<"邻接表为:"<<endl; graph.Print(); cout<<"请输入结点:"<<endl; int vertex; cin>>vertex; cout<<"广度优先遍历(BFS)序列为:"<<endl; graph.BFS(vertex); cout<<endl; cout<<"递归深度优先遍历(DFS)序列为:"<<endl; graph.reset(); graph.DFS1(vertex); cout<<endl; cout<<"非递归深度优先遍历(DFS)序列为:"<<endl; graph.reset(); graph.DFS2(vertex); cout<<endl; return 0;}
截图:
阅读全文
1 0
- 图的遍历(下)——邻接表
- 图——邻接表(深度遍历,广度遍历)
- 图的遍历(数组+邻接表)
- 图的遍历(基于邻接表)
- 图的邻接表存储下的深度优先遍历
- 图的邻接表存储下的广度优先遍历
- 邻接表的图遍历
- 图的邻接表遍历
- 图的遍历——深度优先遍历——邻接表
- 图的遍历——广度优先遍历——邻接表
- 图的邻接表存储及其遍历(使用模板)
- 图(邻接表)的深度、广度优先遍历
- 图的遍历与输出 (邻接矩阵和邻接表)
- 图(邻接表存储)的遍历
- 邻接表实现图的遍历
- 图基于邻接表的遍历
- 图的邻接表及遍历
- 图的邻接表创建以及遍历
- HTTP请求返回状态码详解
- 多重背包
- 融会贯通——最常用的面向对象设计原则“合成复用原则”
- ORACLE 11g 创建数据库时 Enterprise Manager配置失败的解决办法 无法打开OEM的解决办法
- php字符串数组相互转换
- 图的遍历(下)——邻接表
- java异常
- 如何查看linux版本信息
- 以Base64字符串形式上传文件——服务器端Java/Servlet接受请求数据中的字符串内容并转换成文件
- 1051. 复数乘法 (15)
- HTML5的基本结构
- Leetcode352——Data Stream as Disjoint Intervals
- 1008.Gnome Tetravex
- Nginx 教程二:利用nginx搭建静态文件服务、正向代理服务器、反向代理服务器