图的存储最常见的方式是邻接链表和邻接矩阵存储. 邻接矩阵和邻接链表具体是什么这里就不多说了. 由于项目需要, 我需要实现一个能够自动查重的邻接链表, 即不能插入重复结点的邻接链表. 考虑到”不能重复”这一特点, 如果使用stl容器的话, 非map/set/hashmap/hashset莫属. 多的不说, 上代码:
一. 顶点类的定义
enum State { WHITE, GRAY, BLACK }; extern struct Edge; typedef set<Edge> AdjVerticeSet; struct Vertice { AdjVerticeSet adjacentVertices; int id; State color; unsigned int begin; // dfs或bfs发现节点的时间 unsigned int end; // dfs完成访问的时间 int distance; // 记录最短路径 Vertice(int _id = 0) :id(_id), color(WHITE), begin(0), end(0), adjacentVertices(AdjVerticeSet()),distance(1){} void addEdge(Vertice* target); }; typedef pair<int, Vertice*> Node; typedef map<int, Vertice*> VerticeSet;
对顶点添加边
void Vertice::addEdge(Vertice* target) { Edge e = Edge(target); adjacentVertices.insert(e); }
二. 边节点的定义
extern struct Vertice; struct Edge { int weight; Vertice* target; Edge(Vertice* _target, int _weight = 1) :target(_target), weight(_weight){} bool operator<(const Edge& another) const { return target - another.target < 0; } bool operator==(const Edge& another) const { return target - another.target == 0; } bool operator>(const Edge& another) const { return target - another.target > 0; } };
三. 邻接链表的封装类
class Graph { private: // 出度邻接链表 VerticeSet allVertices; #pragma region 内存管理 public: Graph() { allVertices = VerticeSet(); } ~Graph(){ for (auto n : allVertices) { delete n.second; } } #pragma endregion 内存管理 private: void dfs_visit(Vertice* n, int& timestamp); public: void dfs(); void appendEdge(int id_a, int id_b, int weight=1); void appendUndirectedEdge(int id_a, int id_b, int weight = 1) { appendEdge(id_a, id_b, weight); appendEdge(id_b, id_a, weight); } void display(); bool bellmanFord(int source_id); Vertice* operator[](int id) { if (allVertices.count(id)>0) return allVertices.find(id)->second; else return NULL; } void dijkstra(int source_id); }; typedef map<Vertice*, int> ResultList; typedef pair<Vertice*, int> ResultPair;
向邻接链表添加边:
void Graph::appendEdge(int id_a, int id_b, int weight) { if (allVertices.count(id_a) == 0) allVertices.insert(Node(id_a, new Vertice(id_a))); if (allVertices.count(id_b) == 0) allVertices.insert(Node(id_b, new Vertice(id_b))); Vertice* va = allVertices.find(id_a)->second; Vertice* vb = allVertices.find(id_b)->second; va->adjacentVertices.insert(Edge(vb,weight)); }