基于邻接链表和邻接矩阵实现图的各种常用函数C++

来源:互联网 发布:大数据100g百度云 编辑:程序博客网 时间:2024/06/09 17:48

基于图的邻接链表和邻接矩阵实现图的各种常用函数

图最常用的表示方法有邻接链表和邻接矩阵;图的常见函数包括图的建立和销毁,边的插入删除,图的深度优先和广度优先遍历,最小生成树,最短路径等。下面代码在邻接链表和邻接矩阵的基础上分别实现了函数,其中类Graph 是邻接链表表示的,GraphM是邻接矩阵表示的。这里代码比较多,原因是有可能存在多个版本或者多种实现方法。不多说啦,直接上代码。


文件main.cpp

/* * 文件 main.cpp * 功能 示例 * 作者 lmjy * 日期 2017/5/27 **/#include <iostream>#include <fstream>#include <vector>#include <stack>#include <queue>#include "graph.h"using namespace std;int main(){Graph g1(ifstream("g.txt"), 5, 10);//GraphM g1(ifstream("g.txt"),5, 10);cout << "输出图: " << endl;g1.print();cout << endl;cout << "深度遍历0: " << g1.dfs1(0) << endl;cout << "深度遍历3: " << g1.dfs2(3) << endl;cout << "广度遍历4: " << g1.bfs(4) << endl;cout << "最小生成树: " << g1.mstPrim() << endl;cout << "最小生成树: " << g1.mstKruskal() << endl;cout << "BF最短路径(0,2)" << g1.shortestPathBF(0, 2) << endl;cout << "DJ最短路径(0,2)" << g1.shortestPathDijkstra(0, 2) << endl;cout << "BF最短路径(2,0)" << g1.shortestPathBF(2, 0) << endl;cout << "DJ最短路径(2,0)" << g1.shortestPathDijkstra(2, 0) << endl;cout << "BF最短路径(1,4)" << g1.shortestPathBF(1, 4) << endl;cout << "DJ最短路径(1,4)" << g1.shortestPathDijkstra(1, 4) << endl;cout << "BF最短路径(4,1)" << g1.shortestPathBF(4, 1) << endl;cout << "DJ最短路径(4,1)" << g1.shortestPathDijkstra(4, 1) << endl;return 0;}

其中:图结构如图所示


根据图结构书写格式,g.txt如下

0 0 1 31 0 3 52 1 2 63 1 3 24 2 4 25 3 1 16 3 2 47 3 4 68 4 2 79 4 0 3

运行结果如下(Graph类):



运行结果(GraphM类):



下面是图的具体实现文件

文件 graph.h

/* * 文件 graph.h * 功能 图相关的类和函数的声明 * 作者 lmjy * 日期 2017/5/27 **/#ifndef GRAPH_H#define GRAPH_H#define PATHEV 1// 路径集合是边还是点 1为边 0为点#define MAXWEIGHT INT32_MAX >> 1// 表示权值无穷大typedef int Weight;// 权重typedef int Status;// 状态记录typedef int Data[1];// 数据struct EdgeNode {// 边结点int eNum, headv, tailv;// 边编号, 边起点, 边终点Weight weight;// 边权值Status status;// 边状态Data data{ 0 };// 边数据EdgeNode *nextIn, *nextOut;// 入边( 十字链表才需要 ), 出边EdgeNode(int en = 0, int v1 = 0, int v2 = 0, Weight w = 1)// 构造函数, 边编号 起点 尾点 权值:eNum(en), headv(v1), tailv(v2), weight(w), status(0), nextIn(nullptr), nextOut(nullptr) {}EdgeNode(std::istream& is) : status(0), nextIn(nullptr), nextOut(nullptr) {// 输入流, 构成一条边 格式: 边编号 起点 尾点 权值is >> eNum >> headv >> tailv >> weight;}friend bool operator==(const EdgeNode&, const EdgeNode&);// 相等重载, 判断是否同一条边friend bool operator!=(const EdgeNode&, const EdgeNode&);// 不等重载friend std::ostream& operator << (std::ostream&, EdgeNode&);// 输入输出重载, 格式: 边编号 起点 尾点 权值friend std::istream& operator >> (std::istream&, EdgeNode&);};bool operator==(const EdgeNode&, const EdgeNode&);// 边友元函数声明bool operator!=(const EdgeNode&, const EdgeNode&);std::ostream& operator<<(std::ostream&, EdgeNode&);std::istream& operator >> (std::istream&, EdgeNode&);struct VertexNode {// 点结点int vNum;// 点编号Status status;// 点状态Data data{ 0 };// 点数据EdgeNode *nextIn, *nextOut;// 入边, 出边VertexNode(int n1 = 0) :vNum(n1), status(0), nextIn(nullptr), nextOut(nullptr) {}};struct Path {int vStart, vEnd;// 路径的起止点(源和目的节点)Weight dist;// 路径总代价std::vector<int> pathV, pathE;// 存储路径, 分别存中间点编号和边编号Path(int v1 = 0, int v2 = 0, Weight d = 0) :vStart(v1), vEnd(v2), dist(d) {}Path& operator+=(const Path&);// 添加路径在末端friend Path operator+(const Path&, const Path&);// 连接两条路径friend std::ostream& operator <<(std::ostream&, Path&);// 输出重载 格式: 起点 --> 终点 $ 代价 @ <路径>};Path operator+(const Path&, const Path&);std::ostream& operator <<(std::ostream&, Path&);struct Graph {// 图类, 邻接链表表示int vn, en;// 顶点和边的数目std::vector<VertexNode> adjList;// 邻接链表( 十字链表 )Graph(int n1 = 0) :vn(n1), en(0), adjList(n1) {for (int k1(0); k1 < n1; ++k1) adjList[k1].vNum = k1;}Graph(std::istream& is, int n1 = 2, int n2 = 1, bool v = true);// n1 点上限, n2 边上限, v表示有向或者无向图~Graph();void insert(const EdgeNode&,bool = true);// 插入一条边, v表示有向或者无向图, 默认有向int remove(const EdgeNode&, bool = true);// 删除一条边, v表示有向或者无向图, 默认有向, 返回删除的边数int remove(int, bool = true);// 删除一顶点相连的所有边, 返回删除的边数void print(bool = true, std::ostream& = std::cout);Path dfs1(int = 0);// 深度遍历递归  遍历顶点依次存在 Path 中void dfs1(Path&, int = 0);// 深度遍历递归辅助函数Path dfs2(int = 0);// 深度遍历迭代Path bfs(int = 0);// 广度遍历迭代Path mstPrim(int = 0);// 最小生成树 prim Path mstKruskal();// 最小生成树 Kruskal std::vector<Path> shortestPathBF(int = 0);// 最短路径 Bellman Ford 单源Path shortestPathBF(int, int);// 最短路径 Bellman Ford 两点std::vector<Path>  shortestPathDijkstra(int = 0);// 最短路径 Dijkstra 单源Path shortestPathDijkstra(int, int);// 最短路径 Dijkstra 两点};struct GraphM {// 图类, 邻接矩阵表示int vn;std::vector<std::vector<Weight>> wMat;// 邻接矩阵 存储权值, 0表示无穷大std::vector<std::vector<int>> eMat;// 边编号矩阵 存储边序号GraphM(int n1 = 0) :vn(n1), wMat(n1, std::vector<Weight>(n1, 0)), eMat(n1, std::vector<Weight>(n1, -1)) {}GraphM(std::istream& is, int n1 = 2, int n2 = 1, bool v = true);// n1 点上限, n2 边上限, v表示有向或者无向图bool insert(const EdgeNode&, bool = true);// 插入一条边, v表示有向或者无向图, 默认有向int remove(const EdgeNode&, bool = true);// 删除一条边, v表示有向或者无向图, 默认有向, 返回删除的边数int remove(int, bool = true);// 删除一顶点相连的边, 返回删除的边数void print(bool = true, std::ostream& = std::cout);Path dfs1(int = 0);// 深度遍历递归  遍历顶点依次存在 Path 中void dfs1(Path&, std::vector<int>&, int = 0);// 深度遍历递归辅助函数Path dfs2(int = 0);// 深度遍历迭代版本Path bfs(int = 0);// 广度遍历迭代版本Path mstPrim(int = 0);// 最小生成树 prim Path mstKruskal();// 最小生成树 Kruskal std::vector<Path> shortestPathBF(int = 0);// 最短路径 Bellman Ford 单源Path shortestPathBF(int, int);// 最短路径 Bellman Ford 两点std::vector<Path> shortestPathDijkstra(int = 0);// 最短路径 Dijkstra 单源Path shortestPathDijkstra(int, int);// 最短路径 Dijkstra 两点std::vector<std::vector<Path>> shortestPathFloyd() const;// 最短路径 Floyd 全源Path shortestPathFloyd(int, int) const;// 最短路径 Floyd 两点};// 辅助函数int findSet(std::vector<int>&, int = 0);// 集合查找, 返回集合中最后一个元素的索引void vPass(Path&, std::vector<std::vector<int>>&, int, int);// 由节点前驱矩阵确定路径#endif

文件 graph.cpp

/** 文件 graph.cpp* 功能 图类相关的函数的实现* 作者 lmjy* 日期 2017/5/27**/#include <iostream>#include <vector>#include <stack>#include <queue>#include "graph.h"using namespace std;int findSet(std::vector<int>& v, int n) {while (v[n] != n) n = v[n];// 迭代直至最后一个集合的元素return n;}void vPass(Path& p, std::vector<std::vector<int>>& v, int v1, int v2) {if (-1 < v[v1][v2]) {// 由节点前驱矩阵递归中间节点vPass(p, v, v1, v[v1][v2]);p.pathV.push_back(v[v1][v2]);vPass(p, v, v[v1][v2], v2);}}bool operator==(const EdgeNode& e1, const EdgeNode& e2) {return e1.headv == e2.headv && e1.tailv == e2.tailv && e1.eNum == e2.eNum && e1.weight == e2.weight;}bool operator!=(const EdgeNode& e1, const EdgeNode& e2) {return !(e1 == e2);}ostream& operator<<(ostream& os, EdgeNode& e) {os << e.eNum << ends << e.headv << ends << e.tailv << ends << e.weight;return os;}istream& operator >> (istream& is, EdgeNode& e) {is >> e.eNum >> e.headv >> e.tailv >> e.weight;return is;}Path& Path::operator+=(const Path& p) {if (vEnd != p.vStart) return *this;vEnd = p.vEnd;dist += p.dist;pathV.push_back(p.vStart);for (const auto vi : p.pathV) pathV.push_back(vi);for (const auto vi : p.pathE) pathE.push_back(vi);return *this;}Path operator+(const Path& p1, const Path& p2) {Path pt(p1);pt += p2;return pt;}ostream& operator <<(std::ostream& os, Path& pe) {os << pe.vStart << " --> " << pe.vEnd << " $ " << pe.dist << " @ <";#if PATHEVfor (size_t k1(0); k1 < pe.pathE.size(); ++k1) {os << pe.pathE[k1];if (k1 != pe.pathE.size() - 1) os << ", ";}#elsefor (size_t k1(0); k1 < pe.pathV.size(); ++k1) {os << pe.pathV[k1];if (k1 != pe.pathV.size() - 1) os << ", ";}#endifos << ">";return os;}Graph::Graph(istream& is, int n1, int n2, bool v) :vn(n1), en(0), adjList(n1) {for (int k1(0); k1 < n1; ++k1) adjList[k1].vNum = k1;EdgeNode et;while (en < n2 && is >> et) {if (et.headv < vn && et.tailv < vn) insert(et, v);}}Graph::~Graph() {EdgeNode *ep(nullptr);for (int k1(0); k1 < vn; ++k1) {while (ep = adjList[k1].nextOut) {adjList[k1].nextOut = ep->nextOut;delete ep;}}en = vn = 0;adjList.clear();}void Graph::insert(const EdgeNode &e, bool v) {int vn1(max(e.headv, e.tailv) + 1);if (vn < vn1) {adjList.resize(vn1);for (int k1(vn); k1 < vn1; ++k1) adjList[k1].vNum = k1;// 插入新顶点vn = vn1;}EdgeNode *ep = new EdgeNode(e);ep->nextOut = adjList[ep->headv].nextOut;// 插入该边adjList[ep->headv].nextOut = ep;// 下面两句形成十字链表//ep->nextIn = adjList[ep->tailv].nextIn;//adjList[ep->tailv].nextIn = ep;++en;if (!v) {// 插入无向边的对称边EdgeNode *ep = new EdgeNode(e);swap(ep->headv, ep->tailv);ep->nextOut = adjList[ep->headv].nextOut;adjList[ep->headv].nextOut = ep;// 下面两句形成十字链表//ep->nextIn = adjList[ep->tailv].nextIn;//adjList[ep->tailv].nextIn = ep;}}int Graph::remove(const EdgeNode &e, bool v) {if (!(e.headv < vn && e.tailv < vn && adjList[e.headv].nextOut)) return 0;EdgeNode et(e), *ep1(nullptr), *ep2(nullptr), *ep3(nullptr);for (ep2 = adjList[et.headv].nextOut; ep2 && *ep2 != et; ep1 = ep2, ep2 = ep2->nextOut);if (!ep2) return 0;// 查找边是否存在ep1 ? ep1->nextOut = ep2->nextOut : adjList[et.headv].nextOut = ep2->nextOut;// 删除十字链表//for(ep3 = adjList[et.tailv].nextIn; ep3 != ep2; ep1 = ep3, ep3 = ep3->nextIn);//ep1 ? ep1->nextIn = ep3->nextIn : adjList[et.tailv].nextIn = ep3->nextIn;delete ep2;if (!v) {// 删除无向边的对称边swap(et.headv, et.tailv);for (ep2 = adjList[et.headv].nextOut; ep2 && *ep2 != et; ep1 = ep2, ep2 = ep2->nextOut);if (!ep2) return 0;ep1 ? ep1->nextOut = ep2->nextOut : adjList[et.headv].nextOut = ep2->nextOut;// 删除十字链表//for(ep3 = adjList[et.tailv].nextIn; ep3 != ep2; ep1 = ep3, ep3 = ep3->nextIn);//ep1 ? ep1->nextIn = ep3->nextIn : adjList[et.tailv].nextIn = ep3->nextIn;delete ep2;}--en;// 改变边数return 1;}int Graph::remove(int vnum, bool v) {if (!(vnum < vn)) return 0;int ede(0);EdgeNode *ep1(nullptr), *ep2(nullptr);for (int k1(0); k1 < vn; ++k1) {ep1 = nullptr;ep2 = adjList[k1].nextOut;while (ep2) {if (ep2->headv == vnum || ep2->tailv == vnum) {ep1 ? ep1->nextOut = ep2->nextOut : adjList[k1].nextOut = ep2->nextOut;EdgeNode *ep3(nullptr), *ep4(nullptr);// 删除十字链表//for (ep4 = adjList[ep2->tailv].nextIn; ep4 != ep2; ep3 = ep4, ep4 = ep4->nextIn);//ep3 ? ep3->nextIn = ep4->nextIn : adjList[ep2->tailv].nextIn = ep4->nextIn;delete ep2;++ede;}else ep1 = ep2;ep2 = ep1 ? ep1->nextOut : adjList[k1].nextOut;}}if (!v) ede >>= 1;en -= ede;return ede;}void Graph::print(bool v, std::ostream& os) {EdgeNode *ep(nullptr);for (int k1(0); k1 < vn; ++k1) {adjList[k1].status = 1;}for (int k1(0); k1 < vn; ++k1) {ep = adjList[k1].nextOut;while (ep) {if(adjList[ep->tailv].status || v)os << *ep << endl;ep = ep->nextOut;}adjList[k1].status = 0;}os << "the total number of edges in the graph is " << en;}Path Graph::dfs1(int index) {Path p(index < vn ? index : 0, -1, 0);if (vn < 1) return p;for (int k1(0); k1 < vn; ++k1) adjList[k1].status = 0;dfs1(p, p.vStart);return p;/*  该方案没有初始化节点状态Path p(index < vn ? index : 0,-1,0);if (vn < 1) return p;EdgeNode *ep(nullptr);#if PATHEVp.pathE.push_back(index);#elsep.pathV.push_back(index);#endifadjList[p.vStart].status = 1;for (ep = adjList[p.vStart].nextOut; ep; ep = ep->nextOut) {if (adjList[ep->tailv].status) continue;p += dfs1(ep->tailv);}return p;*/}void Graph::dfs1(Path& p, int index) {EdgeNode *ep(nullptr);#if PATHEVp.pathE.push_back(index);#elsep.pathV.push_back(index);#endifadjList[index].status = 1;for (ep = adjList[index].nextOut; ep; ep = ep->nextOut) {if (adjList[ep->tailv].status) continue;p.dist += ep->weight;dfs1(p, ep->tailv);}}Path Graph::dfs2(int index) {Path p(index < vn ? index : 0, -1, 0);if (vn < 1) return p;for (int k1(0); k1 < vn; ++k1) adjList[k1].status = 0;stack<int> st;EdgeNode *ep(nullptr);int kt(p.vStart);while (!st.empty() || !adjList[kt].status) {if (adjList[kt].status) kt = st.top();else {st.push(kt);#if PATHEVp.pathE.push_back(kt);#elsep.pathV.push_back(kt);#endifadjList[kt].status = 1;}for (ep = adjList[kt].nextOut; ep && adjList[ep->tailv].status; ep = ep->nextOut);if (ep) kt = ep->tailv, p.dist += ep->weight;else st.pop();}return p;/*也可以这样实现Path p(index < vn ? index : 0, -1, 0);if (vn < 1) return p;for (int k1(0); k1 < vn; ++k1) adjList[k1].status = 0;stack<int> st;EdgeNode *ep(nullptr);st.push(p.vStart);#if PATHEVp.pathE.push_back(p.vStart);#elsep.pathV.push_back(p.vStart);#endifadjList[p.vStart].status = 1;while (!st.empty()) {for (ep = adjList[st.top()].nextOut; ep && adjList[ep->tailv].status; ep = ep->nextOut);if (ep) {st.push(ep->tailv);#if PATHEVp.pathE.push_back(ep->tailv);#elsep.pathV.push_back(ep->tailv);#endifp.dist += ep->weight;adjList[ep->tailv].status = 1;}else st.pop();}return p;*/}Path Graph::bfs(int index) {Path p(index < vn ? index : 0, -1, 0);if (vn < 1) return p;queue<int> qt;EdgeNode *ep(nullptr);for (int k1(0); k1 < vn; ++k1) adjList[k1].status = 0;qt.push(p.vStart);#if PATHEVp.pathE.push_back(p.vStart);#elsep.pathV.push_back(p.vStart);#endifadjList[p.vStart].status = 1;while (!qt.empty()) {for (ep = adjList[qt.front()].nextOut; ep; ep = ep->nextOut) {if (adjList[ep->tailv].status) continue;qt.push(ep->tailv);#if PATHEVp.pathE.push_back(ep->tailv);#elsep.pathV.push_back(ep->tailv);#endifp.dist += ep->weight;adjList[ep->tailv].status = 1;}qt.pop();}return p;}Path Graph::mstPrim(int st) {st = st < vn ? st : 0;for (int k1(0); k1 < vn; ++k1) adjList[k1].status = 0;Path pret(st, -1, 0);adjList[st].status = 1;vector<Weight> wv(vn, MAXWEIGHT);vector<int> ev(vn, 0);for (int k1(1); k1 < vn; ++k1) {for (auto ep(adjList[st].nextOut); ep; ep = ep->nextOut)if (!adjList[ep->tailv].status && ep->weight < wv[ep->tailv])ev[ep->tailv] = ep->eNum, wv[ep->tailv] = ep->weight;wv[st] = MAXWEIGHT;for (int k2(0); k2 < vn; ++k2)if (!adjList[k2].status && wv[k2] < wv[st]) st = k2;#if PATHEVpret.pathE.push_back(ev[st]);#elsepret.pathV.push_back(ev[st]);#endifpret.dist += wv[st];adjList[st].status = 1;}return pret;}Path Graph::mstKruskal() {Path pret(-1,-1,0);vector<EdgeNode*> ev(en);vector<int> setv(vn);for (int k1(0); k1 < vn; ++k1) {for (auto ep = adjList[k1].nextOut; ep; ep = ep->nextOut) ev[ep->eNum] = ep;}sort(ev.begin(), ev.end(), [](const EdgeNode* e1, const EdgeNode* e2) {return e1->weight < e2->weight; });for (int k1(0); k1 < vn; ++k1) setv[k1] =k1;for (auto ep : ev) {auto s1(findSet(setv, ep->headv)), s2(findSet(setv, ep->tailv));if (s1 != s2) {setv[s1] = s2;#if PATHEVpret.pathE.push_back(ep->eNum);#elsepret.pathV.push_back(ep->eNum);#endifpret.dist += ep->weight;}}return pret;}vector<Path>  Graph::shortestPathBF(int st) {vector<Path> pret(vn, Path(-1,-1,MAXWEIGHT));vector<EdgeNode*> ev;ev.reserve(en << 1);for (int k1(0); k1 < vn; ++k1) {for (auto ep = adjList[k1].nextOut; ep; ep = ep->nextOut) ev.push_back(ep);}st = st < vn ? st : 0;pret[st].dist = 0;for (int k1(1); k1 < vn; ++k1) {for (size_t k2(0); k2 < ev.size(); ++k2) {if (pret[ev[k2]->headv].dist != MAXWEIGHT && ev[k2]->weight < pret[ev[k2]->tailv].dist - pret[ev[k2]->headv].dist) {pret[ev[k2]->tailv].dist = pret[ev[k2]->headv].dist + ev[k2]->weight;pret[ev[k2]->tailv].vStart = ev[k2]->headv;pret[ev[k2]->tailv].vEnd = k2;}}}for (int k1(0), kt(0); k1 < vn; kt = ++k1) {while (-1 < pret[kt].vStart) {pret[k1].pathE.push_back(ev[pret[kt].vEnd]->eNum);kt = pret[kt].vStart;if (k1 != kt) pret[k1].pathV.push_back(kt);}reverse(pret[k1].pathE.begin(), pret[k1].pathE.end());reverse(pret[k1].pathV.begin(), pret[k1].pathV.end());}for (int k1(0); k1 < vn; ++k1) pret[k1].vStart = st, pret[k1].vEnd = k1;return pret;}Path Graph::shortestPathBF(int st, int se) {st = st < vn ? st : 0;se = se < vn ? se : 0;if (st == se) return Path(st, se, 0);vector<Path> pret(vn, Path(-1, -1, MAXWEIGHT));vector<EdgeNode*> ev;ev.reserve(en << 1);for (int k1(0); k1 < vn; ++k1) {for (auto ep = adjList[k1].nextOut; ep; ep = ep->nextOut) ev.push_back(ep);}pret[st].dist = 0;for (int k1(1); k1 < vn; ++k1) {for (size_t k2(0); k2 < ev.size(); ++k2) {if (pret[ev[k2]->headv].dist != MAXWEIGHT && ev[k2]->weight < pret[ev[k2]->tailv].dist - pret[ev[k2]->headv].dist) {pret[ev[k2]->tailv].dist = pret[ev[k2]->headv].dist + ev[k2]->weight;pret[ev[k2]->tailv].vStart = ev[k2]->headv;pret[ev[k2]->tailv].vEnd = k2;}}}for (int kt(se); -1 < pret[kt].vStart;) {pret[se].pathE.push_back(ev[pret[kt].vEnd]->eNum);kt = pret[kt].vStart;if (st != kt) pret[se].pathV.push_back(kt);}reverse(pret[se].pathE.begin(), pret[se].pathE.end());reverse(pret[se].pathV.begin(), pret[se].pathV.end());pret[se].vStart = st, pret[se].vEnd = se;return pret[se];}std::vector<Path>  Graph::shortestPathDijkstra(int st) {vector<Path> pret(vn);for (int k1(0); k1 < vn; ++k1) {adjList[k1].status = 0;pret[k1].dist = MAXWEIGHT;}st = st < vn ? st : 0;pret[st].dist = 0;adjList[st].status = 1;for (int k1(1), kt(st); k1 < vn; ++k1) {for (auto ep(adjList[kt].nextOut); ep; ep = ep->nextOut)if (!adjList[ep->tailv].status && ep->weight < pret[ep->tailv].dist - pret[kt].dist) {pret[ep->tailv].dist = pret[kt].dist + ep->weight;pret[ep->tailv].vStart = kt;pret[ep->tailv].vEnd = ep->eNum;}pret[st].dist = MAXWEIGHT;//先作一变量使用(查找最小顶点时用), 最后再改过来kt = st;for (int k2(0); k2 < vn; ++k2) if (!adjList[k2].status && pret[k2].dist < pret[kt].dist) kt = k2;#if PATHEVpret[kt].pathE = pret[pret[kt].vStart].pathE;pret[kt].pathE.push_back(pret[kt].vEnd);#elsepret[kt].pathV = pret[pret[kt].vStart].pathV;if (st != pret[kt].vStart) pret[kt].pathV.push_back(pret[kt].vStart);#endifpret[kt].vStart = st;pret[kt].vEnd = kt;adjList[kt].status = 1;}pret[st].dist = 0;pret[st].vStart = pret[st].vEnd = st;return pret;}Path Graph::shortestPathDijkstra(int st, int se) {st = st < vn ? st : 0;se = se < vn ? se : 0;if (st == se) return Path(st, se, 0);vector<Path> pret(vn);for (int k1(0); k1 < vn; ++k1) {adjList[k1].status = 0;pret[k1].dist = MAXWEIGHT;}pret[st].dist = 0;adjList[st].status = 1;for (int k1(1), kt(st); k1 < vn; ++k1) {for (auto ep(adjList[kt].nextOut); ep; ep = ep->nextOut)if (!adjList[ep->tailv].status && ep->weight < pret[ep->tailv].dist - pret[kt].dist) {pret[ep->tailv].dist = pret[kt].dist + ep->weight;pret[ep->tailv].vStart = kt;pret[ep->tailv].vEnd = ep->eNum;}pret[kt = st].dist = MAXWEIGHT;//先作一变量使用(查找最小顶点时用), 最后再改过来for (int k2(0); k2 < vn; ++k2)if (!adjList[k2].status && pret[k2].dist < pret[kt].dist) kt = k2;#if PATHEVpret[kt].pathE = pret[pret[kt].vStart].pathE;pret[kt].pathE.push_back(pret[kt].vEnd);#elsepret[kt].pathV = pret[pret[kt].vStart].pathV;if (st != pret[kt].vStart) pret[kt].pathV.push_back(pret[kt].vStart);#endifpret[kt].vStart = st;pret[kt].vEnd = kt;if (kt == se) return pret[se];adjList[kt].status = 1;}return Path(st, se, MAXWEIGHT);}GraphM::GraphM(istream& is, int n1, int n2, bool v):vn(n1), wMat(n1,vector<Weight>(n1,0)), eMat(n1, vector<Weight>(n1, -1)) {int v1, v2, e1;Weight w1;for (int  k1(0); k1 < n2 && is >> e1 >> v1 >> v2 >> w1;) {if (v1 < vn && v2 < vn && (!wMat[v1][v2] || w1 < wMat[v1][v2])) {wMat[v1][v2] = w1;eMat[v1][v2] = e1;++k1;if (!v) {wMat[v2][v1] = w1;eMat[v2][v1] = e1;}}}}bool GraphM::insert(const EdgeNode & e, bool v) {if (!(e.headv < vn && e.tailv < vn && (!wMat[e.headv][e.tailv] || e.weight < wMat[e.headv][e.tailv]))) return false;wMat[e.headv][e.tailv] = e.weight;eMat[e.headv][e.tailv] = e.eNum;if (!v) {wMat[e.tailv][e.headv] = e.weight;eMat[e.tailv][e.headv] = e.eNum;}return true;}int GraphM::remove(const EdgeNode& e, bool v) {if (!(e.headv < vn && e.tailv < vn && wMat[e.headv][e.tailv] && wMat[e.headv][e.tailv] == e.weight && eMat[e.headv][e.tailv]==e.eNum)) return 0;wMat[e.headv][e.tailv] = 0;eMat[e.headv][e.tailv] = -1;if (!v) {wMat[e.tailv][e.headv] = 0;eMat[e.tailv][e.headv] = -1;}return 1;}int GraphM::remove(int v1, bool v) {int ede(0);for (int k1(0); k1 < vn; ++k1) {if (k1 == v1) continue;if (wMat[v1][k1]) {wMat[v1][k1] = 0;eMat[v1][k1] = -1;++ede;}if (wMat[k1][v1]) {wMat[k1][v1] = 0;eMat[k1][v1] = -1;++ede;}}ede = v ? ede : ede >> 1;if (wMat[v1][v1]) {wMat[v1][v1] = 0;eMat[v1][v1] = -1;++ede;}return ede;}void GraphM::print(bool v, ostream& os) {int sum(0);for (int k1(0); k1 < vn; ++k1)for (int k2(v ? 0 : k1); k2 < vn; ++k2)if (wMat[k1][k2]) {os << eMat[k1][k2] << ends << k1 << ends << k2 << ends << wMat[k1][k2] << endl;++sum;}os << "the total number of edges in the graph is " << sum;}Path GraphM::dfs1(int st) {st = st < vn ? st : 0;Path p(st, -1, 0);if (vn < 1) return p;vector<Status> status(vn, 1);dfs1(p, status, st);return p;/*  当status是成员时, 也可以这样实现st = st < vn ? st : 0;Path p(st, -1, 0);if (vn < 1) return p;#if PATHEVp.pathE.push_back(st);#elsep.pathV.push_back(st);#endifstatus[st] = 0;for (int k1(0); k1 < vn; ++k1) {if (wMat[st][k1] && status[k1]) p += dfs1(k1);}return p;*/}void GraphM::dfs1(Path& p, vector<int>& status, int st) {#if PATHEVp.pathE.push_back(st);#elsep.pathV.push_back(st);#endifstatus[st] = 0;for (int k1(0); k1 < vn; ++k1) {if (wMat[st][k1] && status[k1]) {p.dist += wMat[st][k1];dfs1(p, status,k1);}}}Path GraphM::dfs2(int v1) {v1 = v1 < vn ? v1 : 0;Path p(v1, -1, 0);if (vn < 1) return p;vector<Status> status(vn, 1);stack<int> st;int v2;while (!st.empty() || status[v1]) {if (status[v1]) {st.push(v1);#if PATHEVp.pathE.push_back(v1);#elsep.pathV.push_back(v1);#endifstatus[v1] = 0;}else v1 = st.top();for (v2 = 0; v2 < vn && !(wMat[v1][v2] && status[v2]); ++v2);if (v2 < vn) p.dist += wMat[v1][v2], v1 = v2;else st.pop();}return p;/*也可以这样实现v1 = v1 < vn ? v1 : 0;Path p(v1, -1, 0);if (vn < 1) return p;vector<Status> status(vn, 1);stack<int> st;st.push(v1);#if PATHEVp.pathE.push_back(v1);#elsep.pathV.push_back(v1);#endifstatus[v1] = 0;while (!st.empty()) {for (v1 = 0; v2 < vn && !(wMat[st.top()][v1] && status[v1]); ++v1);if (v1 < vn) {st.push(v1);p.pathE.push_back(v1);status[v1] = 0;}else st.pop();}return p;*/}Path GraphM::bfs(int v1) {v1 = v1 < vn ? v1 : 0;Path p(v1, -1, 0);if (vn < 1) return p;vector<Status> status(vn, 1);queue<int> qt;qt.push(v1);#if PATHEVp.pathE.push_back(v1);#elsep.pathV.push_back(v1);#endifstatus[v1] = 0;while (!qt.empty()) {for (int v2(0); v2 < vn; ++v2)if (wMat[qt.front()][v2] && status[v2]) {qt.push(v2);#if PATHEVp.pathE.push_back(v2);#elsep.pathV.push_back(v2);#endifp.dist += wMat[qt.front()][v2];status[v2] = 0;}qt.pop();}return p;}Path GraphM::mstPrim(int st) {st = st < vn ? st : 0;vector<int> status(vn, 1), ev(vn, 0);vector<Weight> wv(vn, 0);Path pret(st, -1, 0);status[st] = 0;for (int k1(1); k1 < vn; ++k1) {for (int k2(0); k2 < vn; ++k2)if (status[k2] && wMat[st][k2] && (!wv[k2] || wMat[st][k2] < wv[k2])) {wv[k2] = wMat[st][k2];ev[k2] = eMat[st][k2];}wv[st] = 0;for (int k2(0); k2 < vn; ++k2)if (status[k2] && wv[k2] && (!wv[st] || wv[k2] < wv[st])) st = k2;#if PATHEVpret.pathE.push_back(ev[st]);#elsepret.pathV.push_back(ev[st]);#endifpret.dist += wv[st];status[st] = 0;}return pret;}Path GraphM::mstKruskal() {Path pret(-1, -1, 0);vector<int> setv(vn);vector<EdgeNode> evec;for (int k1(0); k1 < vn; ++k1) setv[k1] = k1;for (int k1(0); k1 < vn; ++k1)for (int k2(0); k2 < vn; ++k2)if (wMat[k1][k2]) evec.push_back(EdgeNode(eMat[k1][k2], k1, k2, wMat[k1][k2]));sort(evec.begin(), evec.end(), [](const EdgeNode e1, const EdgeNode e2) {return e1.weight < e2.weight; });for (auto e1:evec) {auto s1(findSet(setv, e1.headv)), s2(findSet(setv, e1.tailv));if (s1 != s2) {setv[s1] = s2;#if PATHEVpret.pathE.push_back(e1.eNum);#elsepret.pathV.push_back(e1.eNum);#endifpret.dist += e1.weight;}}return pret;}vector<Path> GraphM::shortestPathBF(int st) {st = st < vn ? st : 0;vector<Path> pret(vn,Path(-1,-1,MAXWEIGHT));pret[st].dist = 0;for (int k1(1); k1 < vn; ++k1) {for (int k2(0); k2 < vn; ++k2)for (int k3(0); k3 < vn; ++k3)if (wMat[k2][k3] && pret[k2].dist != MAXWEIGHT && wMat[k2][k3] < pret[k3].dist - pret[k2].dist) {pret[k3].dist = pret[k2].dist + wMat[k2][k3];pret[k3].vStart = k2;//pret[k3].vEnd = eMat[k2][k3];}}for (int k1(0), kt(0); k1 < vn; kt = ++k1) {while (-1 < pret[kt].vStart) {//pret[k1].pathE.push_back(pret[kt].vEnd);pret[k1].pathE.push_back(eMat[pret[kt].vStart][kt]);kt = pret[kt].vStart;if(k1!=kt) pret[k1].pathV.push_back(kt);}reverse(pret[k1].pathE.begin(), pret[k1].pathE.end());reverse(pret[k1].pathV.begin(), pret[k1].pathV.end());}for (int k1(0); k1 < vn; ++k1) pret[k1].vStart = st, pret[k1].vEnd = k1;return pret;}Path GraphM::shortestPathBF(int st, int se) {st = st < vn ? st : 0;se = se < vn ? se : 0;if (st == se) return Path(st, se, 0);vector<Path> pret(vn, Path(-1, -1, MAXWEIGHT));pret[st].dist = 0;for (int k1(1); k1 < vn; ++k1) {for (int k2(0); k2 < vn; ++k2)for (int k3(0); k3 < vn; ++k3)if (wMat[k2][k3] && pret[k2].dist != MAXWEIGHT && wMat[k2][k3] < pret[k3].dist - pret[k2].dist) {pret[k3].dist = pret[k2].dist + wMat[k2][k3];pret[k3].vStart = k2;//pret[k3].vEnd = eMat[k2][k3];}}for (int kt(se); -1 < pret[kt].vStart;) {pret[se].pathE.push_back(eMat[pret[kt].vStart][kt]);kt = pret[kt].vStart;if(st!=kt) pret[se].pathV.push_back(kt);}reverse(pret[se].pathE.begin(), pret[se].pathE.end());reverse(pret[se].pathV.begin(), pret[se].pathV.end());pret[se].vStart = st, pret[se].vEnd = se;return pret[se];}std::vector<Path>  GraphM::shortestPathDijkstra(int st) {vector<Path> pret(vn,Path(1,0,MAXWEIGHT));st = st < vn ? st : 0;pret[st].dist = 0;pret[st].vStart = 0;// 记录节点状态for (int k1(1), kt(st); k1 < vn; ++k1) {for (int k2(0); k2 < vn; ++k2) if (wMat[kt][k2] && pret[k2].vStart && wMat[kt][k2] < pret[k2].dist - pret[kt].dist) {pret[k2].dist = pret[kt].dist + wMat[kt][k2];pret[k2].vEnd = kt;// 存储前驱节点}pret[kt = st].dist = MAXWEIGHT;//先作一变量使用(查找最小顶点时用), 最后再改过来for (int k2(0); k2 < vn; ++k2)if (pret[k2].vStart && pret[k2].dist < pret[kt].dist) kt = k2;#if PATHEVpret[kt].pathE = pret[pret[kt].vEnd].pathE;pret[kt].pathE.push_back(eMat[pret[kt].vEnd][kt]);#elsepret[kt].pathV = pret[pret[kt].vEnd].pathV;if (st != pret[kt].vEnd) pret[kt].pathV.push_back(pret[kt].vEnd);#endifpret[kt].vStart = 0;}pret[st].dist = 0;for (int k1(0); k1 < vn; ++k1) pret[k1].vStart = st, pret[k1].vEnd = k1;return pret;}Path GraphM::shortestPathDijkstra(int st, int se) {st = st < vn ? st : 0;se = se < vn ? se : 0;if (st == se) return Path(st, se, 0);vector<Path> pret(vn, Path(1, 0, MAXWEIGHT));pret[st].dist = 0;pret[st].vStart = 0;// 记录节点状态for (int k1(1), kt(st); k1 < vn; ++k1) {for (int k2(0); k2 < vn; ++k2)if (wMat[kt][k2] && pret[k2].vStart && wMat[kt][k2] < pret[k2].dist - pret[kt].dist) {pret[k2].dist = pret[kt].dist + wMat[kt][k2];pret[k2].vEnd = kt;// 存储前驱节点}pret[kt = st].dist = MAXWEIGHT;//先作一变量使用(查找最小顶点时用), 最后再改过来for (int k2(0); k2 < vn; ++k2)if (pret[k2].vStart && pret[k2].dist < pret[kt].dist) kt = k2;#if PATHEVpret[kt].pathE = pret[pret[kt].vEnd].pathE;pret[kt].pathE.push_back(eMat[pret[kt].vEnd][kt]);#elsepret[kt].pathV = pret[pret[kt].vEnd].pathV;if (st != pret[kt].vEnd) pret[kt].pathV.push_back(pret[kt].vEnd);#endifif (kt == se) {pret[se].vStart = st;pret[se].vEnd = se;return pret[se];}pret[kt].vStart = 0;}return Path(st,se,MAXWEIGHT);}vector<vector<Path>> GraphM::shortestPathFloyd() const {#if PATHEVauto w(wMat);vector<vector<int>> v(vn, vector<int>(vn));for (int k1(0); k1 < vn; ++k1)for (int k2(0); k2 < vn; ++k2)v[k1][k2] = k1;for (int k1(0); k1 < vn; ++k1)for (int k2(0); k2 < vn; ++k2)for (int k3(0); k3 < vn; ++k3)if (w[k2][k1] && w[k1][k3] && (!w[k2][k3] || w[k2][k1] + w[k1][k3] < w[k2][k3])) {w[k2][k3] = w[k2][k1] + w[k1][k3];v[k2][k3] = v[k1][k3];}vector<vector<Path>> pret(vn, vector<Path>(vn));for (int k1(0); k1 < vn; ++k1)for (int k2(0); k2 < vn; ++k2) {pret[k1][k2].vStart = k1;pret[k1][k2].vEnd = k2;if (!w[k1][k2]) pret[k1][k2].dist = MAXWEIGHT;else {pret[k1][k2].dist = w[k1][k2];for (int k3(k2); k1 != k3; k3 = v[k1][k3]) pret[k1][k2].pathE.push_back(eMat[v[k1][k3]][k3]);reverse(pret[k1][k2].pathE.begin(), pret[k1][k2].pathE.end());}}return pret;#elseauto w(wMat);vector<vector<int>> v(vn, vector<int>(vn, -1));for (int k1(0); k1 < vn; ++k1)for (int k2(0); k2 < vn; ++k2)for (int k3(0); k3 < vn; ++k3)if (w[k2][k1] && w[k1][k3] && (!w[k2][k3] || w[k2][k1] + w[k1][k3] < w[k2][k3])) {w[k2][k3] = w[k2][k1] + w[k1][k3];v[k2][k3] = k1;}vector<vector<Path>> pret(vn, vector<Path>(vn));for (int k1(0); k1 < vn; ++k1)for (int k2(0); k2 < vn; ++k2) {pret[k1][k2].vStart = k1;pret[k1][k2].vEnd = k2;if (!w[k1][k2]) pret[k1][k2].dist = MAXWEIGHT;else {pret[k1][k2].dist = w[k1][k2];vPass(pret[k1][k2], v, k1, k2);}}return pret;#endif}Path GraphM::shortestPathFloyd(int st, int se) const {st = st < vn ? st : 0;se = se < vn ? se : 0;if (st == se) return Path(st, se, 0);#if PATHEVauto w(wMat);vector<vector<int>> v(vn, vector<int>(vn));for (int k1(0); k1 < vn; ++k1)for (int k2(0); k2 < vn; ++k2)v[k1][k2] = k1;for (int k1(0); k1 < vn; ++k1)for (int k2(0); k2 < vn; ++k2)for (int k3(0); k3 < vn; ++k3)if (w[k2][k1] && w[k1][k3] && (!w[k2][k3] || w[k2][k1] + w[k1][k3] < w[k2][k3])) {w[k2][k3] = w[k2][k1] + w[k1][k3];v[k2][k3] = v[k1][k3];}if (!w[st][se]) return Path(st, se, MAXWEIGHT);Path pret(st, se, w[st][se]);for (; st != se; se = v[st][se]) pret.pathE.push_back(eMat[v[st][se]][se]);reverse(pret.pathE.begin(), pret.pathE.end());return pret;#elseauto w(wMat);vector<vector<int>> v(vn, vector<int>(vn, -1));for (int k1(0); k1 < vn; ++k1)for (int k2(0); k2 < vn; ++k2)for (int k3(0); k3 < vn; ++k3)if (w[k2][k1] && w[k1][k3] && (!w[k2][k3] || w[k2][k1] + w[k1][k3] < w[k2][k3])) {w[k2][k3] = w[k2][k1] + w[k1][k3];v[k2][k3] = k1;}if (!w[st][se]) return Path(st, se, MAXWEIGHT);Path pret(st, se, w[st][se]);vPass(pret, v, st, se);return pret;#endif}







原创粉丝点击