图的实现是一件很麻烦的事情,很多同学可能在学数据结构时只是理解了图的基本操作和遍历原理,但并没有动手实践过。在此,我说说我的实现过程。
首先,在草稿纸上画一个图表,这里是有向图,无向图也一样,如下:
我用的是vector+vector容器作为存储结构,如下:vector+vector)
|0|——|1|——|3|
|1|——|2|——|3|
|2|——|3|
|3|
第二步,用自然语言建立这个图,注意数据结构的书一般没有说明图是怎么建立的,在此我简述一下:
1)、加入4个顶点——G.InsertVextex(V);
2)、在两个顶点之间增加有向弧——G.AddEdge(x, y)。
这样图就建立了。
我写了两个Graph的构造函数,也可以直接用一个数组实现1)的操作如下:
vector<VNode> v(4);
Graph G(v);
第三步,广度优先遍历和深度优先遍历。遍历的目的是为了对每个顶点进行一些处理,能够遍历这个图是其他操作的基础。甚至可以用遍历的方法建立这个图,就像我之前用先序遍历建立二叉树一个道理。
这三步完成,图的实现就基本解决了。至于最小生成树、关键路径等问题,以后再说。
/************************* Date : 2013-9-14 Author : DVD0423 Function: 有向图 存储结构如下:(vector+vector) |0|——*——*——* |1|——* |2|——*——* |3|——*——*——*——*——* |4|——*——*——* |5| |6|——*——* |7|——* ***************************/ #include <iostream> #include <vector> #include <queue> using namespace std; typedef int DataType; const DataType INIT_DATA = -1; const int NO_NODE = -1; const int NO_EDGE = -2; class VNode{ public: //data member bool visited; //访问标志 DataType data; //顶点内的数据 vector<int> e; //邻接的边 //member function VNode(DataType val = INIT_DATA, bool flag = false):data(val), visited(flag){} void Visit() { cout<<data<<"\t"; } bool operator== (VNode &y){ if(data == y.data && e == y.e) return true; else return false; } }; class Graph{ public: //data member int vexnum; //图中顶点数 int edgenum; //图中边数 vector<VNode> V; //图的存储结构 //member function Graph() { vexnum = 0; edgenum = 0; } Graph(vector<VNode> &v); int GetVexNum(); int GetEdgeNum(); //节点操作 void InsertVertex(VNode &x); bool DeleteVertex(int x); //边的操作 //bool IfEdge(int x, int y); //判断是否有(x, y)的边 bool AddEdge(int x, int y); bool RemoveEdge(int x, int y); //邻边操作 void PrintNeighbors(int x); // VNode &Neighbor(VNode &x, int n); //x的第n个邻接节点,默认n为第一个 //广度遍历和深度遍历 void BreadthFirstSearch(); void BFS(VNode &x); //队列实现 void DepthFirstSearch(); void DFS(VNode &x); //递归函数 ~Graph(){}; }; Graph::Graph(vector<VNode> &v) { V.assign(v.begin(), v.end()); vexnum = V.size(); edgenum = GetEdgeNum(); } int Graph::GetVexNum() { vexnum = V.size(); return vexnum; } int Graph::GetEdgeNum() { edgenum = 0; for(vector<VNode>::iterator iter = V.begin(); iter != V.end(); ++iter) { edgenum += iter->e.size(); } return edgenum; } void Graph::InsertVertex(VNode &x) { V.push_back(x); vexnum++; } //删除x节点 bool Graph::DeleteVertex(int x) { if(x >= V.size() || x < 0) { cout<<"没有相应节点"<<endl; return false; } vector<VNode>::iterator iter = V.begin()+x; V.erase(iter); vexnum--; return true; } bool Graph::AddEdge(int x, int y) { if((x >= V.size() || x < 0) || (y >= V.size() || y < 0)) { cout<<"没有相应节点"<<endl; return false; } int size = V[x].e.size(); for(vector<int>::iterator iter = V[x].e.begin(); iter != V[x].e.end(); ++iter) { if(V[*iter] == V[y]) //已经有(x, y) { cout<<"已经有弧(x, y)"<<endl; return false; } } V[x].e.push_back(y); //没有,则把y加入x的邻边队列中 edgenum++; return true; } bool Graph::RemoveEdge(int x, int y) { if((x >= V.size() || x < 0) || (y >= V.size() || y < 0)) { cout<<"没有相应节点"<<endl; return false; } for(vector<int>::iterator iter = V[x].e.begin(); iter != V[x].e.end(); ++iter) { if(V[*iter] == V[y]) { V[x].e.erase(iter); edgenum--; return true; } } cout<<"没有弧(x, y)"<<endl; return false; } //邻边操作 void Graph::PrintNeighbors(int x) { cout<<"列出节点"<<x<<"的所有邻接节点"<<endl; for(vector<int>::iterator iter = V[x].e.begin(); iter != V[x].e.end(); ++iter) { cout<<*iter<<"\t"; } cout<<endl; } VNode &Graph::Neighbor(VNode &x, int n = 1) { if(n > x.e.size() || n <= 0) { cout<<"没有相应边"<<endl; exit(0); } return V[(x.e[n-1])]; } /****** 遍历 **********/ void Graph::BreadthFirstSearch() { for(int i = 0; i != vexnum; ++i) { if(!V[i].visited) BFS(V[i]); } for(vector<VNode>::iterator k = V.begin(); k != V.end(); ++k) k->visited = false; } void Graph::BFS(VNode &x) { queue<VNode> q; q.push(x); while(!q.empty()) { VNode &_x = q.front(); if(!_x.visited) { _x.Visit(); _x.visited = true; int size = _x.e.size(); for(int i = 0; i < size; ++i) { VNode &w = V[_x.e[i]]; if(!w.visited) { w.Visit(); w.visited = true; q.push(w); } } } q.pop(); } } void Graph::DepthFirstSearch() { for(int i = 0; i != vexnum; ++i) { if(!V[i].visited) DFS(V[i]); } for(vector<VNode>::iterator k = V.begin(); k != V.end(); ++k)//改变访问标志,以便下次访问 k->visited = false; } void Graph::DFS(VNode &x) { x.Visit(); x.visited = true; int size = x.e.size(); for(int i = 0; i < size; ++i) { VNode &w = V[x.e[i]]; if(!w.visited) DFS(w); } }
下面是main函数
int main() { Graph G; vector<VNode> v(4); for(int i = 0; i != 4; ++i) { v[i].data = i; //节点信息 G.InsertVertex(v[i]); } //Graph G(v); G.AddEdge(0, 1); G.AddEdge(0, 3); G.AddEdge(1, 2); G.AddEdge(2, 3); G.AddEdge(1, 3); G.BreadthFirstSearch(); return 0; }