diff --git a/YASI_12/ds.graph.h b/YASI_12/ds.graph.h index a640dde..db95213 100644 --- a/YASI_12/ds.graph.h +++ b/YASI_12/ds.graph.h @@ -1,6 +1,9 @@ #pragma once #include "common.h" +#include +#include #include "ds.doublylinkedlist.h" +#include "ds.IntLinearProbingHashTable.h" using namespace std; namespace yasi{ @@ -13,11 +16,11 @@ class EdgeBase; template struct Edge{ Element element; - V *pStart, *pEnd; + float weight; + V *start, *end; + Edge(V* v1 = NULL, V* v2 = NULL, float w = 0) : start(v1), end(v2), weight(w){} }; -template -typedef DoublyLinkedList< E > EdgeList; template struct Vertex{ @@ -25,25 +28,157 @@ struct Vertex{ typedef Vertex self; typedef Edge edge; public: - typedef DoublyLinkedList< edge > EdgeList; + typedef DoublyLinkedList< edge* > EdgeList; int id; Element element; EdgeList* pInEdges; EdgeList* pOutEdges; + + Vertex(int id = 0) :id(id){ + pInEdges = new EdgeList; + pOutEdges = new EdgeList; + } + + virtual ~Vertex(){ + DELETE_SAFE(pInEdges); + DELETE_SAFE(pOutEdges); + } +}; + +class IGraph{ +public: + virtual ~IGraph(){} + virtual int numVertices() const = 0; + virtual int numEdges() const = 0; }; /// Adjacency list data structure -template -class Graph{ +// directed weighted graph +template +class Graph : public IGraph{ + /////////////// enable testing ///////////// + friend class GraphTest; public: typedef Vertex VertexType; typedef Edge EdgeType; typedef DoublyLinkedList VertexList; typedef DoublyLinkedList EdgeList; protected: - VertexList* vertexList; - EdgeList* edgeList; + VertexList vertexList; + EdgeList edgeList; + const bool _weighted; + + void clear(){ + for (VertexList::iterator i = vertexList.begin(); i != vertexList.end(); i++){ + DELETE_SAFE(*i); + } + vertexList.clear(); + for (EdgeList::iterator i = edgeList.begin(); i != edgeList.end(); i++){ + DELETE_SAFE(*i); + } + edgeList.clear(); + } +public: + Graph(bool weighted = true) :_weighted(weighted){ + } + virtual ~Graph(){ + } + int numVertices() const override{ + return vertexList.size(); + } + int numEdges() const override{ + return edgeList.size(); + } + EdgeType* addEdge(VertexType* v1, VertexType* v2, float w = 0){ + EdgeType* edge = new EdgeType(v1, v2, w); + edgeList.pushBack(edge); + v1->pOutEdges->pushBack(edge); + v2->pInEdges->pushBack(edge); + return edge; + } + VertexType* addVertex(int id){ + VertexType* pVertex = new VertexType(id); + vertexList.pushBack(pVertex); + return pVertex; + } + VertexType* addVertex(int id, VertexElement e){ + VertexType* pVertex = addVertex(id); + pVertex->element = e; + return pVertex; + } + + // strEdgeList contains non-empty lines + // one line for each edge + // line format: vid1 vid2 weight + void loadFromString(string strEdgeList){ + clear(); + stringstream inp(trim(strEdgeList)); + + // use a temporary hashtable + IntLinearProbingHashTable< VertexType* > ht; + + while (! inp.eof()){ + int vid1, vid2; + float w; + // vertices + inp >> vid1 >> vid2; + // edge weight + if (_weighted){ + inp >> w; + } + else{ + w = 0; + } + + // create vertices + // add them to the graph if not already there + VertexType **ppv1, **ppv2; + VertexType *pv1, *pv2; + + // first vertex + ppv1 = ht.get(vid1); + if (!ppv1){ + pv1 = addVertex(vid1); + ht.put(vid1, pv1); + } + else{ + pv1 = *ppv1; + } + // second vertex + ppv2 = ht.get(vid2); + if (!ppv2){ + pv2 = addVertex(vid2); + ht.put(vid2, pv2); + } + else{ + pv2 = *ppv2; + } + // create edge + addEdge(pv1, pv2, w); + } + } +}; // class Graph + +class GraphTest : public yasi::Test{ +public: + void loadFromString(){ + Graph g; + + // simple triangle + string triangle = + "1 2 12\n" + "1 3 13\n" + "2 3 23\n"; + g.loadFromString(triangle); + + // test + ASSERT_EQ(3, g.numVertices()); + ASSERT_EQ(3, g.numEdges()); + } + }; -} -} \ No newline at end of file +ADD_TEST_F(GraphTest, loadFromString); + +} // namespace ds +} // namespace yasi \ No newline at end of file diff --git a/YASI_12/main.cpp b/YASI_12/main.cpp index 2f585eb..8ae0255 100644 --- a/YASI_12/main.cpp +++ b/YASI_12/main.cpp @@ -12,6 +12,7 @@ #include "ds.intlinearprobinghashtable.h" #include "ds.linearprobinghashtable.h" #include "ds.hopscotchhashtable.h" +#include "ds.graph.h" //#include "Sorter.h" diff --git a/YASI_12/utils.h b/YASI_12/utils.h index b52d71f..9ae4a17 100644 --- a/YASI_12/utils.h +++ b/YASI_12/utils.h @@ -1,5 +1,9 @@ #pragma once #include "common.h" +#include +#include +#include +#include #include using namespace std; @@ -83,6 +87,29 @@ int whichPowerOfTwo(unsigned int n){ } } + +////////////////////////////////////////// +//// string trimming functions from +//// http://stackoverflow.com/questions/216823/whats-the-best-way-to-trim-stdstring +///////////////////////////////////////// + +// trim from start +inline std::string <rim(std::string &s) { + s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun(std::isspace)))); + return s; +} + +// trim from end +inline std::string &rtrim(std::string &s) { + s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::ptr_fun(std::isspace))).base(), s.end()); + return s; +} + +// trim from both ends +inline std::string &trim(std::string &s) { + return ltrim(rtrim(s)); +} + ///////////// enable in compile-time a certain code block depending on boolean predicate ///////////// ///////////// also, check if a certain class contains a certain function /////////////////////////////// //////////////////////// see http://stackoverflow.com/questions/257288/is-it-possible-to-write-a-c-template-to-check-for-a-functions-existence#264088 diff --git a/gtest-1.7.0/msvc/gtest/gtest.tlog/CL.read.1.tlog b/gtest-1.7.0/msvc/gtest/gtest.tlog/CL.read.1.tlog index 5f26b72..805ee4b 100644 Binary files a/gtest-1.7.0/msvc/gtest/gtest.tlog/CL.read.1.tlog and b/gtest-1.7.0/msvc/gtest/gtest.tlog/CL.read.1.tlog differ diff --git a/gtest-1.7.0/msvc/gtest/gtest.tlog/CL.write.1.tlog b/gtest-1.7.0/msvc/gtest/gtest.tlog/CL.write.1.tlog index 20e58ca..e24205d 100644 Binary files a/gtest-1.7.0/msvc/gtest/gtest.tlog/CL.write.1.tlog and b/gtest-1.7.0/msvc/gtest/gtest.tlog/CL.write.1.tlog differ diff --git a/gtest-1.7.0/msvc/gtest/gtest.tlog/Lib-link.read.1.tlog b/gtest-1.7.0/msvc/gtest/gtest.tlog/Lib-link.read.1.tlog index aa3c582..d65ea8a 100644 Binary files a/gtest-1.7.0/msvc/gtest/gtest.tlog/Lib-link.read.1.tlog and b/gtest-1.7.0/msvc/gtest/gtest.tlog/Lib-link.read.1.tlog differ diff --git a/gtest-1.7.0/msvc/gtest/gtest.tlog/Lib-link.write.1.tlog b/gtest-1.7.0/msvc/gtest/gtest.tlog/Lib-link.write.1.tlog index 39397cd..38bc9ba 100644 Binary files a/gtest-1.7.0/msvc/gtest/gtest.tlog/Lib-link.write.1.tlog and b/gtest-1.7.0/msvc/gtest/gtest.tlog/Lib-link.write.1.tlog differ diff --git a/gtest-1.7.0/msvc/gtest/gtest.tlog/cl.command.1.tlog b/gtest-1.7.0/msvc/gtest/gtest.tlog/cl.command.1.tlog index 8ae87d6..f0a687c 100644 Binary files a/gtest-1.7.0/msvc/gtest/gtest.tlog/cl.command.1.tlog and b/gtest-1.7.0/msvc/gtest/gtest.tlog/cl.command.1.tlog differ diff --git a/gtest-1.7.0/msvc/gtest/gtest.tlog/gtest.lastbuildstate b/gtest-1.7.0/msvc/gtest/gtest.tlog/gtest.lastbuildstate index 4d2b89b..2520c8c 100644 --- a/gtest-1.7.0/msvc/gtest/gtest.tlog/gtest.lastbuildstate +++ b/gtest-1.7.0/msvc/gtest/gtest.tlog/gtest.lastbuildstate @@ -1,2 +1,2 @@ #TargetFrameworkVersion=v4.0:PlatformToolSet=v120:EnableManagedIncrementalBuild=false:VCToolArchitecture=Native32Bit -Debug|Win32|D:\DropBox\My Dropbox\Projects\C++\YASI\| +Debug|Win32|C:\Saad\Dropbox\Projects\C++\YASI\| diff --git a/gtest-1.7.0/msvc/gtest/gtest.tlog/lib.command.1.tlog b/gtest-1.7.0/msvc/gtest/gtest.tlog/lib.command.1.tlog index 00c683f..1e2396b 100644 Binary files a/gtest-1.7.0/msvc/gtest/gtest.tlog/lib.command.1.tlog and b/gtest-1.7.0/msvc/gtest/gtest.tlog/lib.command.1.tlog differ diff --git a/gtest-1.7.0/msvc/gtest/vc120.idb b/gtest-1.7.0/msvc/gtest/vc120.idb index 56f7d00..ebc39c8 100644 Binary files a/gtest-1.7.0/msvc/gtest/vc120.idb and b/gtest-1.7.0/msvc/gtest/vc120.idb differ diff --git a/gtest-1.7.0/msvc/gtestd.lib b/gtest-1.7.0/msvc/gtestd.lib index 8a8264d..61335ca 100644 Binary files a/gtest-1.7.0/msvc/gtestd.lib and b/gtest-1.7.0/msvc/gtestd.lib differ