图的深度优先(非递归)、广度优先、最小生成树的C++实现
2012-11-15 21:12
831 查看
头文件:
实现文件:
测试文件:
/***************************************************************************** * algraph.h * * Adjacency List Based Undirected Graph. * * This is a C++ template class for undirected graph with an adjacency list * representation. It provedes the general operations for graph, such as * insertVertex, removeVertex, insertEdge, removeEdge, getVertexNumber, * getEdgeNumber, getData, getWeight, getNextDst, and so on. * * It also includes the Depth First Search (nonrecursion version), Breadth * First Search and Minimum Span Tree algorithms. * * When debugging, use #define BOUNDS_CHECK above your "#include algraph.h" * line. When done debugging, comment out #define BOUNDS_CHECK for better * performance. * * Zhang Ming, 2009-10 *****************************************************************************/ #ifndef ALGRAPH_H #define ALGRAPH_H #include <iostream> #include <cstdlib> #include <cassert> #include <constants.h> #include <stack.h> #include <queue.h> using namespace std; namespace itlab { /** * graph's edge */ template<typename Weight> struct Edge { int dst; Weight cost; Edge<Weight> *next; Edge( int d, Weight c, Edge<Weight> *p=NULL ) : dst(d), cost(c), next(p) { } }; /** * graph's vertex */ template<typename Object, typename Weight> struct Vertex { Object data; Edge<Weight> *adj; Vertex( Object x=Object(), Edge<Weight> *p=NULL ) : data(x), adj(p) { } }; /** * adjacency list based graph */ template<typename Object, typename Weight> class ALGraph { public: static const Weight MAXWEIGHT = Weight(32767); static const Weight MINWEIGHT = Weight(-32768); explicit ALGraph( int n=INITSIZE ); ~ALGraph(); int getVertexNumber() const; int getEdgeNumber() const; Object getData( int i ) const; int getIndex( const Object &x ) const; Weight getWeight( const Object &x1, const Object &x2 ) const; int getNextDst( const Object &x ) const; int getNextDst( const Object &x1, const Object &x2 ) const; void insertVertex( const Object &x ); void removeVertex( const Object &x ); void insertEdge( const Object &x1, const Object &x2, Weight c ); void removeEdge( const Object &x1, const Object &x2 ); void dfs(); void dfs( int start, bool *visited ); void bfs(); void bfs( int start, bool *visited ); void minSpanTree( int start, int *addedVertex, int *conectedVertex, Weight *lowCost ); private: int curSize; int maxSize; int edgeNum; Vertex<Object, Weight> *vertexArray; }; #include <algraph-impl.h> } // namespace itlab #endif // ALGRAPH_H
实现文件:
/***************************************************************************** * algraph-impl.h * * Implementation for ALGraph class. * * Zhang Ming, 2009-10 *****************************************************************************/ /** * constructors and destructor */ template<typename Object, typename Weight> ALGraph<Object,Weight>::ALGraph( int n ) { maxSize = n; curSize = 0; edgeNum = 0; vertexArray = new Vertex<Object,Weight>[maxSize]; if( vertexArray == NULL ) { cerr << "Out of memory!"; exit(1); } for( int i=0; i<maxSize; ++i ) vertexArray[i].adj = NULL; } template<typename Object, typename Weight> ALGraph<Object,Weight>::~ALGraph() { for( int i=0; i<maxSize; ++i ) { Edge<Weight> *p = vertexArray[i].adj; while( p != NULL ) { vertexArray[i].adj = p->next; delete p; p = vertexArray[i].adj; } } delete []vertexArray; } /** * Get the vertex number of the graph. */ template<typename Object, typename Weight> inline int ALGraph<Object,Weight>::getVertexNumber() const { return curSize; } /** * Get the edge number of the graph. */ template<typename Object, typename Weight> inline int ALGraph<Object,Weight>::getEdgeNumber() const { return edgeNum; } /** * Return the content of vertex "i". */ template<typename Object, typename Weight> inline Object ALGraph<Object,Weight>::getData( int i ) const { #ifdef BOUNDS_CHECK assert( 0 <= i ); assert( i < curSize ); #endif return vertexArray[i].data; } /** * Return the index of vertex "x", if there is no shuch vertex, return -1. */ template<typename Object, typename Weight> inline int ALGraph<Object,Weight>::getIndex( const Object &x ) const { for( int i=0; i<curSize; ++i ) if( vertexArray[i].data == x ) return i; return -1; } /** * Return weight on the edge between vertex "x1" and "x2". */ template<typename Object, typename Weight> Weight ALGraph<Object,Weight>::getWeight( const Object &x1, const Object &x2 ) const { int v1 = getIndex(x1), v2 = getIndex(x2); if( v1 == -1 ) { cerr << "There is no vertex: " << x1 << endl; return Weight(0); } else if( v2 == -1 ) { cerr << "There is no vertex: " << x2 << endl; return Weight(0); } else { Edge<Weight> *p = vertexArray[v1].adj; while( p != NULL && p->dst != v2 ) p = p->next; if( p != NULL ) return p->cost; else { cerr << "There is no edge between " << x1 << " and " << x2 << endl; return Weight(0); } } } /** * Get the position of the next adjacency point of vertex "x", * if there is no next adjacendy vertex, return -1; */ template<typename Object, typename Weight> int ALGraph<Object,Weight>::getNextDst( const Object &x ) const { int i = getIndex(x); if( i == -1 ) { cerr << "There is no vertex: " << x << endl; return -1; } else { Edge<Weight> *p = vertexArray[i].adj; if( p != NULL ) return p->dst; else return -1; } } template<typename Object, typename Weight> int ALGraph<Object,Weight>::getNextDst( const Object &x1, const Object &x2 ) const { int v1 = getIndex(x1), v2 = getIndex(x2); if( v1 == -1 ) { cerr << "There is no vertex: " << x1 << endl; return -1; } else if( v2 == -1 ) { cerr << "There is no vertex: " << x2 << endl; return -1; } else { Edge<Weight> *p = vertexArray[v1].adj; while( p != NULL && p->dst != v2 ) p = p->next; if( p != NULL && p->next != NULL ) return p->next->dst; else return -1; } } /** * Insert a new vertex "x". If the vertex array is full, output * the FULL warning. */ template<typename Object, typename Weight> void ALGraph<Object,Weight>::insertVertex( const Object &x ) { if( curSize < maxSize ) vertexArray[curSize++] = Vertex<Object,Weight>( x, NULL ); else cerr << "The vertex table is full!" << endl; } /** * Remove the vertex "x". */ template<typename Object, typename Weight> void ALGraph<Object,Weight>::removeVertex( const Object &x ) { int i = 0, v = getIndex(x); if( v == -1 ) cerr << "There is no vertex: " << x << endl; else { Edge<Weight> *p, *r, *s; while( vertexArray[v].adj != NULL ) { p = vertexArray[v].adj; i = p->dst; r = vertexArray[i].adj; s = NULL; while( r != NULL && r->dst != v ) { s = r; r = r->next; } if( s != NULL ) s->next = r->next; else vertexArray[i].adj = r->next; delete r; vertexArray[v].adj = p->next; delete p; edgeNum--; } vertexArray[v] = vertexArray[--curSize]; vertexArray[curSize].adj = NULL; p = vertexArray[v].adj; while( p != NULL ) { r = vertexArray[p->dst].adj; while( r != NULL ) { if( r->dst == curSize ) { r->dst = v; break; } else r = r->next; } p = p->next; } } } /** * Insert an edge (x1,x2) with weight "c". If the edge already exist then * return false, else return true. */ template<typename Object, typename Weight> void ALGraph<Object,Weight>::insertEdge( const Object &x1, const Object &x2, Weight c ) { int v1 = getIndex(x1), v2 = getIndex(x2); if( v1 == -1 ) cerr << "There is no vertex: " << x1 << endl; else if( v2 == -1 ) cerr << "There is no vertex: " << x2 << endl; else { Edge<Weight> *p = vertexArray[v1].adj, *q = NULL; while( p != NULL && p->dst != v2 ) p = p->next; if( p != NULL ) { cerr << "The edge is already existence!" << endl; return; } p = new Edge<Weight>( v2, c, vertexArray[v1].adj ); vertexArray[v1].adj = p; q = new Edge<Weight>( v1, c, vertexArray[v2].adj ); vertexArray[v2].adj = q; edgeNum++; } } /** * Remove the edge (x1,x2). */ template<typename Object, typename Weight> void ALGraph<Object,Weight>::removeEdge( const Object &x1, const Object &x2 ) { int v1 = getIndex(x1), v2 = getIndex(x2); if( v1 == -1 ) cerr << "There is no vertex: " << x1 << endl; else if( v2 == -1 ) cerr << "There is no vertex: " << x2 << endl; else { Edge<Weight> *p = vertexArray[v1].adj, *q = NULL, *r = p; while( p != NULL && p->dst != v2 ) { q = p; p = p->next; } if( p != NULL ) { if( p == r ) vertexArray[v1].adj = p->next; else { q->next = p->next; delete p; } } else { cerr << "There is no such edge between " << x1 << " and " << x2 << endl; return; } p = vertexArray[v2].adj; q = NULL; r = p; while( p->dst != v1 ) { q = p; p = p->next; } if( p == r ) vertexArray[v2].adj = p->next; else { q->next = p->next; delete p; } edgeNum--; } } /** * The nonrecursion implementation for Depth First Search algorithm. */ template<typename Object, typename Weight> void ALGraph<Object,Weight>::dfs() { bool *visited = new bool( curSize ); for( int i=0; i<curSize; ++i ) visited[i] = false; for( int i=0; i<curSize; ++i ) if( !visited[i] ) dfs( i, visited ); delete visited; } template<typename Object, typename Weight> void ALGraph<Object,Weight>::dfs( int start, bool *visited ) { Edge<Weight> *p; Stack< Edge<Weight>* > s( curSize ); cout << getData( start ) << endl; visited[start] = true; s.push( vertexArray[start].adj ); while( !s.isEmpty() ) { s.getTop( p ); while( p != NULL && visited[p->dst] ) p = p->next; if( p != NULL ) { int d = p->dst; cout << getData( d ) << endl; visited[d] = true; s.push( vertexArray[d].adj ); } else s.pop(); } } /** * The nonrecursion implementation for Breadth First Search algorithm. */ template<typename Object, typename Weight> void ALGraph<Object,Weight>::bfs() { bool *visited = new bool( curSize ); for( int i=0; i<curSize; ++i ) visited[i] = false; for( int i=0; i<curSize; ++i ) if( !visited[i] ) bfs( i, visited ); delete visited; } template<typename Object, typename Weight> void ALGraph<Object,Weight>::bfs( int start, bool *visited ) { Queue<int> q; cout << getData( start ) << endl; visited[start] = true; q.enqueue( start ); int a = 0; Edge<Weight> *p = NULL; while( !q.isEmpty() ) { q.dequeue( a ); p = vertexArray[a].adj; while( p != NULL ) { int d = p->dst; if( !visited[d] ) { cout << getData( d ) << endl; visited[d] = true; q.enqueue( d ); } p = p->next; } } } /** * The Prim algorithm for Minimum Span Tree. */ template<typename Object, typename Weight> void ALGraph<Object,Weight>::minSpanTree( int start, int *addedVertex, int *conectedVertex, Weight *lowCost ) { #ifdef BOUNDS_CHECK assert( 0 <= start ); assert( start < curSize ); #endif bool *mark = new bool[curSize]; for( int i=0; i<curSize; ++i ) { addedVertex[i] = -1; conectedVertex[i] = -1; lowCost[i] = MAXWEIGHT; mark[i] = false; } addedVertex[0] = start; conectedVertex[0] = start; lowCost[start] = 0; mark[start] = true; for( int i=1; i<curSize; ++i ) { Edge<Weight> *p = vertexArray[start].adj; while( p != NULL ) { int j = p->dst; if( !mark[j] && lowCost[j]>p->cost ) { lowCost[j] = p->cost; conectedVertex[j] = start; } p = p->next; } Weight min = MAXWEIGHT; for( int j=0; j<curSize; ++j ) if( !mark[j] && lowCost[j] < min ) { min = lowCost[j]; start = j; } mark[start] = true; addedVertex[i] = start; } /* output the result... for( int i=0; i<curSize; ++i ) cout << "( " << addedVertex[i] << ", " << conectedVertex[addedVertex[i]] << ", " << lowCost[addedVertex[i]] << " )" << endl; */ } /** * Reload the "<<" operator. */ template<typename Object, typename Weight> ostream& operator<<( ostream &out, const ALGraph<Object,Weight> &g ) { int verNum = g.getVertexNumber(), edgeNum = g.getEdgeNumber(); out << "This graph has " << verNum << " vertexes and " << edgeNum << " edges." << endl; for( int i=0; i<verNum; ++i ) { Object x1 = g.getData(i); out << x1 << " : "; int j = g.getNextDst(x1); if( j != -1 ) { Object x2 = g.getData(j); out << "( " << x1 << ", " << x2 << ", " << g.getWeight(x1,x2) << " )" << " "; do { j = g.getNextDst( x1, x2 ); if( j != -1 ) { x2 = g.getData(j); out << "( " << x1 << ", " << x2 << ", " << g.getWeight(x1,x2) << " )" << " "; } else break; } while( j != -1 ); } out << endl; } return out; }
测试文件:
/***************************************************************************** * graph_test.cpp * * Adjacency List Based Undirected Graph testing. * * Zhang Ming, 2009-10 *****************************************************************************/ #define BOUNDS_CHECK #include <iostream> #include <graph.h> using namespace std; using namespace itlab; int main() { ALGraph<char, int> g( 6 ); g.insertVertex( 'A' ); g.insertVertex( 'B' ); g.insertVertex( 'C' ); g.insertVertex( 'D' ); g.insertVertex( 'E' ); g.insertVertex( 'F' ); cout << g << endl << endl; g.insertEdge( 'A', 'B', 6 ); g.insertEdge( 'A', 'C', 1 ); g.insertEdge( 'A', 'D', 5 ); g.insertEdge( 'B', 'C', 5 ); g.insertEdge( 'B', 'E', 3 ); g.insertEdge( 'C', 'D', 5 ); g.insertEdge( 'C', 'E', 6 ); g.insertEdge( 'C', 'F', 4 ); g.insertEdge( 'D', 'F', 2 ); g.insertEdge( 'E', 'F', 6 ); cout << g << endl << endl; cout << "The Depth First Search traverse:" << endl; g.dfs(); cout << endl << endl; cout << "The Breadth First Search traverse:" << endl; g.bfs(); cout << endl << endl; cout << "The Minimum Span Tree:" << endl; int vtxNum = g.getVertexNumber(); int start = 0, *addedVertex = new int[vtxNum], *conectedVertex = new int[vtxNum], *lowCost = new int[vtxNum]; g.minSpanTree( start, addedVertex, conectedVertex, lowCost ); for( int i=0; i<vtxNum; ++i ) cout << "( " << addedVertex[i] << ", " << conectedVertex[addedVertex[i]] << ", " << lowCost[addedVertex[i]] << " )" << endl; cout << endl << endl; g.removeVertex('B'); cout << g << endl << endl; g.removeEdge( 'A', 'B' ); cout << g << endl << endl; g.removeEdge( 'A', 'D' ); cout << g << endl << endl; g.removeEdge( 'E', 'D' ); cout << g << endl << endl; cout << "The depth first search traverse:" << endl; g.dfs(); cout << endl << endl; cout << "The Breadth First Search traverse:" << endl; g.bfs(); cout << endl << endl; delete []addedVertex; delete []conectedVertex; delete []lowCost; return 0; }
相关文章推荐
- C++ 图的深度搜索广度搜索和最小生成树代码实现
- 邻接表c源码(构造邻接矩阵,深度优先遍历,广度优先遍历,最小生成树prim,kruskal算法)
- C/C++代码实现图(有向图)的深度,广度优先遍历
- Java实现图:邻接矩阵表示、深度优先搜索、广度优先搜索、无向图的最小生成树
- 深度广度优先遍历最小生成树
- 数据结构-图-Java实现:有向图 图存储(邻接矩阵),最小生成树,广度深度遍历,图的连通性,最短路径
- java-二叉树广度优先实现、深度优先之前序实现(非递归)
- c++实现广度优先和深度优先查找目录结构
- C++实现图的邻接矩阵存储和广度、深度优先遍历实例分析
- 数据结构-图-Java实现:有向图 图存储(邻接矩阵),最小生成树,广度深度遍历,图的连通性,最短路径
- 图的邻接表(广度优先遍历,深度优先遍历,最小生成树(Kruskal算法))
- 图的深度优先和广度优先遍历(图以邻接表表示,由C++面向对象实现)
- 图的遍历和生成树求解实现|图遍历,生成树,实现,邻接矩阵,邻接表,深度广度遍历,最小生成树
- 最大流与最小割C++实现2——深度优先搜索
- 数据结构-图-Java实现:有向图 图存储(邻接矩阵),最小生成树,广度深度遍历,图的连通性,最短路径
- 数据结构学习_图(1)深度优先搜索、广度优先搜索和最小生成树
- BFS_DFS深度广度优先C++实现。
- 图与路径(深度优先,广度优先,最小生成树)
- 邻接矩阵c源码(构造邻接矩阵,深度优先遍历,广度优先遍历,最小生成树prim,kruskal算法)
- 有向图深度优先与广度优先算法的C++实现