From dc7bd3abf6ae77a3ea9bcb48360c2a3d96831f81 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 29 Sep 2014 22:14:14 -0400 Subject: [PATCH] Fixed bugs. Now BFS can search in a graph :) Signed-off-by: unknown --- YASI_12/alg.graph.h | 60 ++++++++++++++++++++++++++++----------------- YASI_12/ds.graph.h | 43 ++++++++++++++++++-------------- 2 files changed, 62 insertions(+), 41 deletions(-) diff --git a/YASI_12/alg.graph.h b/YASI_12/alg.graph.h index 1361b83..d6909a9 100644 --- a/YASI_12/alg.graph.h +++ b/YASI_12/alg.graph.h @@ -17,7 +17,7 @@ namespace graph{ template // graph class BFS{ ////////////// enable testing ////////////// - friend class BSFTest; + friend class BFSTest; public: typedef typename G::VertexType VertexType; typedef typename G::EdgeType EdgeType; @@ -32,20 +32,15 @@ namespace graph{ VERTEX_VISITED }; // the BFS ordering of vertices + // indexed by vertex id int* pBfsParent; /////////////////////////////////////////////////// // override thesse function in child classes // for your own BSF visit action - virtual void visitVertexBeforeSchedulingNeighbors(VertexType* v){ - // do nothing - } - virtual void visitVertexAfterSchedulingNeighbors(VertexType* v){ - // do nothing - } - virtual void visitEdge(EdgeType* e){ - // do nothing - } + virtual void visitVertexBeforeSchedulingNeighbors(VertexType* v) = 0; + virtual void visitVertexAfterSchedulingNeighbors(VertexType* v) = 0; + virtual void visitEdge(EdgeType* e) = 0; ////////////////////////////////////////////////// void clear(){ DELETE_ARR_SAFE(pBfsParent); @@ -67,10 +62,14 @@ namespace graph{ pBfsParent = new int[n]; // record BFS tree // init - const int srcId = src->id; DoublyLinkedList q; - int* vertexStatus = new int[n]; + // the source vertex + const int srcId = src->id; + vertexStatus[srcId] = VERTEX_DISCOVERED; + pBfsParent[srcId] = -1; + q.pushBack(src); + // other vertices for (int i = 0; i < n; i++){ if (i == srcId) continue; vertexStatus[i] = VERTEX_UNDISCOVERED; @@ -78,10 +77,6 @@ namespace graph{ pBfsParent[i] = -1; } - // the source vertex - vertexStatus[srcId] = VERTEX_DISCOVERED; - pBfsParent[srcId] = -1; - q.pushBack(src); // the traversal while (!q.empty()){ @@ -107,7 +102,7 @@ namespace graph{ int neighborId = neighborVertex->id; if (vertexStatus[neighborId] == VERTEX_UNDISCOVERED){ // schedule a visit to the neighbor - vertexStatus[neighborId] == VERTEX_DISCOVERED; + vertexStatus[neighborId] = VERTEX_DISCOVERED; pBfsParent[neighborId] = currentId; q.pushBack(neighborVertex); } @@ -136,21 +131,25 @@ namespace graph{ template class MyBFS : public BFS < G > { + ////////// enable testing ///////// + friend class BSFTest; protected: typedef BFS parent; typedef typename parent::VertexType VertexType; typedef typename parent::EdgeType EdgeType; stringstream visitSequence; + ///////////// override visit methods ///////////// + virtual void visitVertexBeforeSchedulingNeighbors(VertexType* v) override { + visitSequence << v->label << " "; + } + virtual void visitVertexAfterSchedulingNeighbors(VertexType* v) override {}; + virtual void visitEdge(EdgeType* e) override {}; public: MyBFS() : parent(){ } virtual ~MyBFS(){ - } - /////////// override specific visit functions ////// - virtual void visitVertexBeforeScheudlingNeighbors(VertexType* pVertex){ - visitSequence << pVertex->label << " "; } string getVisitSequence() const{ return visitSequence.str(); @@ -172,12 +171,17 @@ namespace graph{ G g; g.loadFromString(strPath); string expectedVisitSequence = "1 2 3 4 5 "; + int bfsParent[] = {-1, 1, 2, 3, 4}; MyBFS bfs; VertexType* src = *(g.getVertexList()->begin()); bfs.search(g, src); string actualVisitSequence = bfs.getVisitSequence(); ASSERT_EQ(expectedVisitSequence, actualVisitSequence); + // bfs tree + for (int i = 1; i < g.numVertices(); i++){ + ASSERT_EQ(i - 1, bfs.pBfsParent[i]); + } } { SCOPED_TRACE("binary tree"); @@ -198,6 +202,11 @@ namespace graph{ bfs.search(g, src); string actualVisitSequence = bfs.getVisitSequence(); ASSERT_EQ(expectedVisitSequence, actualVisitSequence); + // bfs tree + for (int i = 1; i < g.numVertices(); i++){ + int parentId = (i%2) ? i/2 : i/2 - 1; + ASSERT_EQ(parentId, bfs.pBfsParent[i]); + } } { @@ -217,7 +226,11 @@ namespace graph{ bfs.search(g, src); string actualVisitSequence = bfs.getVisitSequence(); ASSERT_EQ(expectedVisitSequence, actualVisitSequence); - } + // bfs tree + for (int i = 1; i < g.numVertices(); i++){ + ASSERT_EQ(i - 1, bfs.pBfsParent[i]); + } + } { SCOPED_TRACE("complete graph K5"); string strK5 = @@ -251,6 +264,9 @@ namespace graph{ bfs.search(g, src); string actualVisitSequence = bfs.getVisitSequence(); ASSERT_EQ(expectedVisitSequence, actualVisitSequence); + // bfs tree + const int expectedBfsParent[] = {-1, 0, 0, 0, 0}; // first vertex is parent of all others + ASSERT_EQ(true, arrcmp(expectedBfsParent, bfs.pBfsParent, g.numVertices())); } } }; diff --git a/YASI_12/ds.graph.h b/YASI_12/ds.graph.h index 8669ef3..c05719b 100644 --- a/YASI_12/ds.graph.h +++ b/YASI_12/ds.graph.h @@ -18,16 +18,17 @@ struct Edge{ }; -template +template struct Vertex{ protected: typedef Vertex self; typedef Edge edge; public: typedef DoublyLinkedList< edge* > EdgeList; + typedef LabelType LabelType; int id; // id assigned by the graph data structure - int label; // label assigned with input description + LabelType label; // label assigned with input description Element element; // possibly composite information stored at this vertex EdgeList* pInEdges; @@ -59,6 +60,7 @@ class Graph : public IGraph{ friend class GraphTest; public: typedef Vertex VertexType; + typedef typename VertexType::LabelType VertexLabelType; typedef Edge EdgeType; typedef DoublyLinkedList VertexList; typedef DoublyLinkedList EdgeList; @@ -84,8 +86,8 @@ class Graph : public IGraph{ edgeList.clear(); } public: - // by default, unweighted directed graph - Graph(bool weighted = false) :_weighted(weighted), _vertexId(0){ + // by default, weighted directed graph + Graph(bool weighted = true) :_weighted(weighted), _vertexId(0){ } virtual ~Graph(){ clear(); @@ -103,14 +105,16 @@ class Graph : public IGraph{ v2->pInEdges->pushBack(edge); return edge; } - VertexType* addVertex(int label){ + VertexType* addVertex(VertexLabelType label){ + // VertexLabelType is just int VertexType* pVertex = new VertexType(_vertexId++); pVertex->label = label; vertexList.pushBack(pVertex); return pVertex; } - VertexType* addVertex(int label, VertexElement e){ - VertexType* pVertex = addVertex(id); + VertexType* addVertex(VertexLabelType label, VertexElement e){ + // VertexLabelType is just int + VertexType* pVertex = addVertex(label); pVertex->element = e; return pVertex; } @@ -134,24 +138,25 @@ class Graph : public IGraph{ // comments char string commentChars = ";#"; - // use a temporary hashtable + // use a temporary hashtable for id-ing the vertices IntLinearProbingHashTable< VertexType* > ht; while (! inp.eof()){ // comment line char leadingChar = inp.peek(); - if (commentChars.find(leadingChar) != string::npos ||// comment - leadingChar == '\n'){ // empty line - // skip this comment line + bool isComment = commentChars.find(leadingChar) != string::npos; + bool isBlankLine = leadingChar == '\n'; + if (isComment || isBlankLine ){ + // skip this line inp.ignore(INT_MAX, '\n'); continue; } - int vid1, vid2; + VertexLabelType vLabel1, vLabel2; float w; // vertices - inp >> vid1 >> vid2; + inp >> vLabel1 >> vLabel2; // edge weight if (_weighted){ inp >> w; @@ -166,19 +171,19 @@ class Graph : public IGraph{ VertexType *pv1, *pv2; // first vertex - ppv1 = ht.get(vid1); + ppv1 = ht.get(vLabel1); if (!ppv1){ - pv1 = addVertex(vid1); - ht.put(vid1, pv1); + pv1 = addVertex(vLabel1); + ht.put(vLabel1, pv1); } else{ pv1 = *ppv1; } // second vertex - ppv2 = ht.get(vid2); + ppv2 = ht.get(vLabel2); if (!ppv2){ - pv2 = addVertex(vid2); - ht.put(vid2, pv2); + pv2 = addVertex(vLabel2); + ht.put(vLabel2, pv2); } else{ pv2 = *ppv2;