图的分类
有/无向图
如果给图的每条边规定一个方向,那么得到的图称为有向图。在有向图中,与一个节点相关联的边有出边和入边之分。相反,边没有方向的图称为无向图。
下面介绍图的两种存储结构
1、邻接矩阵
用一个一维数组存放图中所有顶点数据;用一个二维数组存放顶点间关系(边或弧)的数据,这个二维数组称为邻接矩阵。邻接矩阵又分为有向图邻接矩阵和无向图邻接矩阵
邻接矩阵的思想图
代码实现
- int GetIndex(const V& v)//获取顶点
- {
- for (size_t i=0;i<_size;i++)
- {
- if(_vertex[i]==v)
- return i;
- }
- throw std::invalid_argument("顶点赋值错误");
- }
- void AddEdge(const V& src,const V& dst,const W& w)//增加矩阵中的点
- {
- size_t srcIndex=GetIndex(src);
- size_t dstIndex=GetIndex(dst);
- _matrix[srcIndex][dstIndex]=w;
- if(_isDirection==false)
- _matrix[dstIndex][srcIndex]=w;
- }
2、邻接表
图的邻接矩阵存储方法跟树的孩子链表示法相类似,是一种顺序分配和链式分配相结合的存储结构。如这个表头结点所对应的顶点存在相邻顶点,则把相邻顶点依次存放于表头结点所指向的单向链表中。
邻接表的思想图
邻接表的代码实现
- int GetIndex(const V& v)
- {
- for (int i=0;i<_vertex.size();i++)
- {
- if(_vertex[i]==v)
- return i;
- }
- throw std::invalid_argument("顶点赋值错误");
- }
- void _AddEdge(size_t src,size_t dst,const W& w)
- {
- // _table[src][dst]._w=w;
- Node* cur=new Node(src,dst,w);
- cur->Next=_table[src];
- _table[src]=cur;
- }
- void AddEdge(const V& src,const W& w)
- {
- int srcIndex=GetIndex(src);
- int dstIndex=GetIndex(dst);
- if (_isDirection)
- {
- _AddEdge(srcIndex,dstIndex,w);
- }
- else
- {
- _AddEdge(srcIndex,w);
- _AddEdge(dstIndex,srcIndex,w);
- }
- }
邻接表的深度优先遍历,类似于二叉树的前序遍历
一个节点知道遍历到无路可走才遍历旁边的节点
代码实现,这里用vector实现
- void DFS(const V& v)
- {
- vector<bool> visted(_vertex.size(),false);
- cout<<v;
- _DFS(GetIndex(v),visted);
- for(size_t i=0;i<_vertex.size();i++)
- {
- if(visted[i]==false)
- {
- cout<<_vertex[i];
- visted[i]=true;
- _DFS(i,visted);
- }
- }
- cout<<"NULL"<<endl;
- }
- void _DFS(size_t src,vector<bool>& visted)
- {
- visted[src]=true;
- Node* cur=_table[src];
- cout<<"["<<src<<"]->";
- while (cur)
- {
- if(visted[cur->_dst]==false)
- {
- cout<<_vertex[cur->_dst];
- visted[cur->_dst]=true;
- _DFS(cur->_dst,visted);
- }
- cur=cur->Next;
- }
- }
邻接表的广度优先遍历
一个节点把它周围的节点全部都遍历完,才会进行前进遍历
代码实现,这里用队列实现,队列有先进先出的特点,符合此算法
- void _BFS(size_t src,vector<bool>& visted)
- {
- visted[src]=true;
- cout<<"["<<src<<"]->";
- queue<size_t> q;
- q.push(src);
- while (!q.empty())
- {
- src=q.front();
- q.pop();
- Node* cur=_table[src];
- while (cur)
- {
- if(visted[cur->_dst]==false)
- {
- cout<<_vertex[cur->_dst]<<"["<<cur->_dst<<"]"<<"-> ";
- visted[cur->_dst]=true;
- q.push(cur->_dst);
- }
- cur=cur->Next;
- }
- }
- cout<<endl;
- }
- void BFS(const V& v)
- {
- vector<bool> visted(_vertex.size(),false);
- cout<<v;
- _BFS(GetIndex(v),visted);
- }
附全部代码及其测试
临街矩阵
邻接表及其遍历
- #include <iostream>
- #include <string>
- #include <vector>
- using namespace std;
- template<class V,class W>
- class GraphMatrix
- {
- public:
- GraphMatrix(V* vertex,size_t size,bool isDirection=false,const int invalid=0 )
- :_vertex(new V[size]),_size(size),_isDirection(isDirection)
- {
- _matrix=new W*[size];
- for(size_t i=0;i<size;i++)
- {
- _vertex[i]=vertex[i];
- _matrix[i]=new W[size];
- for (size_t j=0;j<size;j++)
- {
- _matrix[i][j]=invalid;
- }
- }
- }
- ~GraphMatrix()
- {
- delete[] _vertex;
- delete[] _matrix;
- _size=0;
- }
- int GetIndex(const V& v)//获取顶点
- {
- for (size_t i=0;i<_size;i++)
- {
- if(_vertex[i]==v)
- return i;
- }
- throw std::invalid_argument("顶点赋值错误");
- }
- void AddEdge(const V& src,const W& w)//增加矩阵中的点
- {
- size_t srcIndex=GetIndex(src);
- size_t dstIndex=GetIndex(dst);
- _matrix[srcIndex][dstIndex]=w;
- if(_isDirection==false)
- _matrix[dstIndex][srcIndex]=w;
- }
- void PrintMaxtix()
- {
- for(size_t i=0;i<_size;i++)
- {
- for(size_t j=0;j<_size;j++)
- {
- cout<<_matrix[i][j]<<" ";
- }
- cout<<endl;
- }
- }
- protected:
- V* _vertex;
- W** _matrix;
- size_t _size;
- bool _isDirection;
- };
- void TestGraphMatrix()
- {
- string v[4]={"西安","宝鸡","咸阳","延安"};
- GraphMatrix<string,size_t> gm(v,4);//无向图
- cout<<"无向图邻接矩阵:"<<endl;
- gm.AddEdge("西安",7);
- gm.AddEdge("西安",200);
- gm.AddEdge("西安","延安",500);
- gm.AddEdge("宝鸡",100);
- gm.AddEdge("宝鸡",200);
- gm.AddEdge("咸阳",100);
- gm.PrintMaxtix();
- GraphMatrix<string,size_t> gm1(v,4,true);//有向图
- cout<<"有向图邻接矩阵:"<<endl;
- gm1.AddEdge("西安",7);
- gm1.AddEdge("西安",200);
- gm1.AddEdge("西安",500);
- gm1.AddEdge("宝鸡",100);
- gm1.AddEdge("宝鸡",200);
- gm1.AddEdge("咸阳",100);
- gm1.PrintMaxtix();
- }
- #include <iostream>
- #include <string>
- #include <vector>
- #include <queue>
- using namespace std;
- template<class V,class W>
- class GraphLink
- {
- struct Node
- {
- W _w;
- size_t _src;
- size_t _dst;
- Node* Next;
- Node(int src=0,int dst=0,const W& w=W())
- :_src(src),_dst(dst),_w(w),Next(NULL)
- {}
- };
- public:
- GraphLink(const V* vertex,int size,bool isDirection=false)
- :_isDirection(isDirection)
- {
- _vertex.resize(size);
- _table.resize(size);
- for(size_t i=0;i<size;i++)
- {
- _vertex[i]=vertex[i];
- }
- }
- int GetIndex(const V& v)
- {
- for (int i=0;i<_vertex.size();i++)
- {
- if(_vertex[i]==v)
- return i;
- }
- throw std::invalid_argument("顶点赋值错误");
- }
- void _AddEdge(size_t src,w);
- }
- }
- void DFS(const V& v)
- {
- vector<bool> visted(_vertex.size(),visted);
- }
- cur=cur->Next;
- }
- }
- void _BFS(size_t src,visted);
- }
- void PrintLink()
- {
- for (size_t i=0;i<_vertex.size();++i)
- {
- cout<<_vertex[i]<<"["<<i<<"]->";
- Node* cur=_table[i];
- while (cur)
- {
- cout<<_vertex[cur->_dst]<<" ["<<cur->_dst<<"]"<<cur->_w<<"->";
- cur=cur->Next;
- }
- cout<<"NULL"<<endl;
- }
- }
- protected:
- vector<V> _vertex;
- vector<Node*> _table;
- bool _isDirection;
- };
- void TestGraphLink()
- {
- string v[4]={"西安","延安"};
- GraphLink<string,4);//无向图邻接表
- cout<<"无向图邻接表:"<<endl;
- gm.AddEdge("西安",100);
- gm.PrintLink();
- cout<<"无向图DFS遍历:"<<endl;//深度优先遍历
- gm.DFS("西安");
- gm.DFS("宝鸡");
- gm.DFS("咸阳");
- gm.DFS("延安");
- cout<<"无向图BFS遍历:"<<endl;//广度优先遍历
- gm.BFS("西安");
- gm.BFS("宝鸡");
- gm.BFS("咸阳");
- gm.BFS("延安");
- GraphLink<string,true);//有向图邻接表
- cout<<"有向图邻接表:"<<endl;
- gm1.AddEdge("西安",100);
- gm1.PrintLink();
- cout<<"有向图DFS遍历:"<<endl;//深度优先遍历
- gm1.DFS("西安");
- gm1.DFS("宝鸡");
- gm1.DFS("咸阳");
- gm1.DFS("延安");
- cout<<"有向图BFS遍历:"<<endl;//广度优先遍历
- gm1.BFS("西安");
- gm1.BFS("宝鸡");
- gm1.BFS("咸阳");
- gm1.BFS("延安");
- }
测试代码
测试结果
- #include "Graph.h"
- #include "GraphLink.h"
- #include<stdlib.h>
- int main()
- {
- TestGraphMatrix();
- TestGraphLink();
- system("pause");
- return 0;
- }