diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..fe861fb --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,28 @@ +cmake_minimum_required(VERSION 3.1.0) +project(Graph) + +# # Debug(GDB) +# SET(CMAKE_BUILD_TYPE "Debug") +# SET(CMAKE_CXX_FLAGS_DEBUG "ENV{CXXFLAGS} -O0 -Wall -g2 -ggdb") +# SET(CMAKE_CXX_FLAGS_RELEASE "ENV{CXXFLAGS} -O3 -Wall") + +# Collect file +aux_source_directory(./src SRC) +include_directories(./include) + +set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) +set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) + +# Generate lib +add_library(Graph SHARED ${SRC}) + +# Header file +target_include_directories(Graph +PUBLIC +./include) + +# Compile +add_executable(Main main.cpp) + +# Link +target_link_libraries(Main Graph) \ No newline at end of file diff --git a/Introduction.md b/Introduction.md new file mode 100644 index 0000000..37c8dca --- /dev/null +++ b/Introduction.md @@ -0,0 +1,20 @@ +# Introduction +This project contains a shared library(`libGraph.dll`) of Graph and related algorithms. The `Main.exe` is a demo. + +# Graph +Default is **Direcrted Network**. Contains both directions and weights. You can set the weight to a constant number and connect 2 vertex with 2 contary direction edge to simplify it. + +## Initial +Graph contains too much information and is hard to initial by typing on keyboard. So please create a `Initial.txt` file in this +form: + +```txt +A B C D E F * +A 12 E +A 1 B +C 1 A +E 2 F +``` +1, First line is the vertecis data, using a '*' character as end label. + +2, Following are the edges. Each line indicates an edge, left to right are tail vertex, weight, head vertex. \ No newline at end of file diff --git a/include/Alias.h b/include/Alias.h new file mode 100644 index 0000000..2895e39 --- /dev/null +++ b/include/Alias.h @@ -0,0 +1,10 @@ +#ifndef __ALIAS_H__ +#define __ALIAS_H__ + +struct Alias +{ + using size_t = unsigned int; +}; + + +#endif \ No newline at end of file diff --git a/include/Edge.h b/include/Edge.h new file mode 100644 index 0000000..34f1d7c --- /dev/null +++ b/include/Edge.h @@ -0,0 +1,33 @@ +#ifndef __EDGE_H__ +#define __EDGE_H__ +#include "Alias.h" +#include "Graph.h" + +// Directed edge, and has weight +class Edge : public Alias +{ + friend class Graph; +private: + // The vertex that the edge comes from. + size_t tailVtx; + + // The vertex that the edge comes to. + size_t headVtx; + + Edge* headList; + Edge* tailList; + + double weight; + +public: + Edge(size_t Head_Vertex, size_t Tail_Vertex, Edge* Head_List=nullptr, Edge* Tail_list=nullptr); + ~Edge(); +}; + +Edge ::Edge(size_t Head_Vertex, size_t Tail_Vertex, Edge* Head_List, Edge* Tail_list) +:headList(Head_List), tailList(Tail_list), headVtx(Head_Vertex), tailVtx(Tail_Vertex) +{} + +Edge ::~Edge() +{} +#endif \ No newline at end of file diff --git a/include/Graph.h b/include/Graph.h new file mode 100644 index 0000000..15a9c46 --- /dev/null +++ b/include/Graph.h @@ -0,0 +1,24 @@ +#ifndef __GRAPH_H__ +#define __GRAPH_H__ +#include "Edge.h" +#include "Vertex.h" +#include "Alias.h" +#include +#include +#include + +const std::string Path{"./../../rsrc/"}; + +// Using Orthogonal list +class Graph : public Alias +{ + friend class Vertex; + friend class Edge; +private: + std::vector vertexList; + +public: + Graph(std::istream& input); + ~Graph(); +}; +#endif \ No newline at end of file diff --git a/include/Vertex.h b/include/Vertex.h new file mode 100644 index 0000000..fba971b --- /dev/null +++ b/include/Vertex.h @@ -0,0 +1,33 @@ +#ifndef __VERTEX_H__ +#define __VERTEX_H__ +#include "Edge.h" +#include "Alias.h" +#include "Graph.h" + +// Basic element of graph +class Vertex: public Alias +{ + friend class Graph; + friend bool operator==(const Vertex& a, const Vertex& b); +private: + char data; + Edge * firstIn, *firstOut; + +public: + Vertex(char Data, Edge * First_In = nullptr, Edge * First_Out = nullptr); + Vertex(); + ~Vertex(); +}; +// Support function 'std::find' work. +inline bool operator==(const Vertex& a, const Vertex& b){ return a.data == b.data; } + +Vertex ::Vertex(char Data, Edge * First_In, Edge * First_Out) +:data(Data), firstIn(First_In), firstOut(First_Out) +{} + +Vertex ::Vertex() +:data(), firstIn(nullptr), firstOut(nullptr){} + +Vertex ::~Vertex() +{} +#endif \ No newline at end of file diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..2a3e643 --- /dev/null +++ b/main.cpp @@ -0,0 +1,10 @@ +#include "Graph.h" +#include +#include +// Demo + +int main(){ + std::ifstream in(Path + "Initial.txt"); + Graph g(in); + return 0; +} \ No newline at end of file diff --git a/rsrc/Initial.txt b/rsrc/Initial.txt new file mode 100644 index 0000000..a4b91ab --- /dev/null +++ b/rsrc/Initial.txt @@ -0,0 +1,14 @@ +A B C D E F G H * +A 1 B +B 2 C +C 3 A +C 1 D +D 4 E +E 3 F +F 10 G +G 11 H +H 1 A +A 1 E +A 2 G +B 19 G +B 2 D \ No newline at end of file diff --git a/src/Graph.cpp b/src/Graph.cpp new file mode 100644 index 0000000..e3dbee2 --- /dev/null +++ b/src/Graph.cpp @@ -0,0 +1,93 @@ +#include "Graph.h" +#include +#include +#include +using std::string; +using std::vector; +using std::cout; +using std::endl; + +Graph::Graph(std::istream& input) +{ + char buffer; + + // Get Vertex data + while(input >> buffer && buffer != '*'){ + vertexList.push_back(Vertex(buffer)); + } + // Get edges and connect + typedef vector::iterator Iter; + Iter tail, head; + size_t weight; + + while (!input.eof()) + { + // Get edges information + input >> buffer; + tail = std::find(vertexList.begin(), vertexList.end(), Vertex(buffer)); + + input >> weight; + + input >> buffer; + head = std::find(vertexList.begin(), vertexList.end(), Vertex(buffer)); + + // Add to list + // Link adjacent list + auto tailList_tail{(*tail).firstOut}; + auto NewEdge{new Edge(head - vertexList.begin(), tail - vertexList.begin())}; + if(tailList_tail){ + while(tailList_tail->tailList){ + tailList_tail = tailList_tail->tailList; + } + tailList_tail->tailList = NewEdge; + }else{ + (*tail).firstOut = NewEdge; + } + + // Link de-adjacent list + auto headList_tail{(*head).firstIn}; + if(headList_tail){ + while(headList_tail->headList){ + headList_tail = headList_tail->headList; + } + headList_tail->headList = NewEdge; + }else{ + (*head).firstIn = NewEdge; + } + } + + // Test + // cout << "Vertex" << "\t" << "Tail" << "\t" << "Head" << endl; + for(auto& i : vertexList){ + cout << i.data << "\t"; + + auto ptr{i.firstIn}; + while (ptr){ + cout << ptr->headVtx << ' ' << ptr->tailVtx << '\t'; + ptr = ptr->tailList; + } + cout << endl; + } +} + +Graph::~Graph() +{ + for(auto& vtx : vertexList){ + // cout<<"Delete: "; + if(!vtx.firstOut) continue; + if(!vtx.firstOut->tailList){ + // cout << vtx.firstOut->headVtx <<' '<< vtx.firstOut->tailVtx << '\t'; + delete vtx.firstOut; + }else { + auto back{vtx.firstOut}, prior{back->tailList}; + while(prior){ + // cout << back->headVtx << ' ' << back->tailVtx << '\t'; + delete back; + back = prior; + prior = prior->tailList; + } + // cout<< back->headVtx << ' ' << back->tailVtx << endl; + delete back; + } + } +} \ No newline at end of file