图的实现、无向图的最小生成树、有向图的最短路径



graph.h

#ifndef __GRAPH__
#define __GRAPH__

#include <iostream>
#include <queue>
using namespace std;

class DisjointSet;

template <class TypeOfEdge>
class Graph {
public:
  virtual bool insert(int u, int v, TypeOfEdge weight) = 0;
  virtual bool remove(int u, int v) = 0;
  virtual bool modify(int u, int v, TypeOfEdge weight) = 0;
  virtual bool exist(int u, int v) const = 0;
  virtual int numOfVer() const {return vers;}
  virtual int numOfEdge() const {return edges;}

protected:
  int vers;
  int edges;
};

//有向加权图的邻接表实现
//作为无权图使用时,可将weight置1,权值一样
//作为无向图使用时,插入和删除时需将两个方向的边均插入或删除,修改weight时同样
template <class TypeOfVer, class TypeOfEdge>
class AdjListGraph : public Graph<TypeOfEdge>{
public:
  //这里为了方便,所有成员函数写成内联函数的形式

  //构造一个只有结点没有边的图
  AdjListGraph(int v, const TypeOfVer *d, bool isWeightedFlag, bool isDirectedFlag){
    vers = v;
    edges = 0;
    isWeighted = isWeightedFlag;
    isDirected = isDirectedFlag;

    verList = new VerNode[vers];
    for (int i = 0; i < vers; ++i) {
      verList[i].ver = d[i];
    }
  }

  ~AdjListGraph(){
    for (int i = 0; i < vers; ++i) {
      EdgeNode *p, *pre;
      p = verList[i].head;
      while (p != NULL){
        pre = p;
        p = p->next;
        delete pre;
      }
    }

    delete [] verList;
  }

  bool insert(int u, int v, TypeOfEdge weight = 0) {
    if (u < 0 || u > vers - 1 || v < 0 || v > vers - 1)
      return false;

    if (exist(u, v))
      return false;

    verList[u].head = new EdgeNode(v, weight, verList[u].head);
    if (!isDirected)
      verList[v].head = new EdgeNode(u, weight, verList[v].head);
    ++edges;
    
    return true;
  }

  bool remove(int u, int v) {
    bool flag = removeCore(u, v);
    if (!isDirected)
      flag &= removeCore(v, u);
    return flag;
  }

  bool removeCore(int u, int v) {
    if (u < 0 || u > vers - 1 || v < 0 || v > vers - 1)
      return false;

    EdgeNode *p = verList[u].head;
    if (p == NULL){
      return false;
    }
    //删除结点为头结点
    if (p->end == v){
      verList[u].head = p->next;
      delete p;
      --edges;
      return true;
    }
    
    //找到删除结点或找不到
    EdgeNode *pre = p;
    p = p->next;
    while (p != NULL && p->end != v) {
      pre = p;
      p = p->next;
    }
    //找不到
    if (p == NULL){
      return false;
    }
    //找到
    pre->next = p->next;
    delete p;
    --edges;

    return true;
  }

  bool modify(int u, int v, TypeOfEdge weight) {
    bool flag = modifyCore(u, v, weight);
    if (!isDirected)
      flag &= modifyCore(v, u, weight);
    return flag;
  }

  bool modifyCore(int u, int v, TypeOfEdge weight) {
    EdgeNode *p = verList[u].head;
    while (p != NULL && p->end != v) {
      p = p->next;
    }
    if (p == NULL) {
      return false;
    }
    p->weight = weight;
    return true;
  }

  bool exist(int u, int v) const {
    EdgeNode *p = verList[u].head;
    while (p != NULL && p->end != v) {
      p = p->next;
    }
    if (p == NULL) {
      return false;
    }
    return true;
  }

  //深度优先遍历
  void dfs(int startVer = 0) const {
    bool *visited = new bool[vers];
    for (int i = 0; i < vers; ++i)
      visited[i] = false;

    int j = 0;
    for (int i = startVer; i < vers + startVer; ++i){
      j = i % vers;
      if (visited[j])
        continue;
      dfsCore(j, visited);
      cout << endl; //每一行为一棵深度优先生成树
    }
  }

  //广度优先遍历
  void bfs(int startVer = 0) const {
    bool *visited = new bool[vers];
    for (int i = 0; i < vers; ++i)
      visited[i] = false;

    queue<int> q;
    int j = 0;
    for (int i = startVer; i < vers + startVer; ++i){
      j = i % vers;
      if (visited[j])
        continue;
      q.push(j);
      while (!q.empty()) {
        //访问当前结点
        int v = q.front();
        q.pop();
        if (visited[v])
          continue;
        cout << verList[v].ver << '\t';
        visited[v] = true;
        
        //当前结点的后继结点放入队列
        EdgeNode *p = verList[v].head;
        while (p != NULL) {
          if (!visited[p->end]) {
            q.push(p->end);
          }
          p = p->next;
        }
      }
      cout << endl; //每一行为一棵广度优先生成树
    }
  }

  //欧拉回路
  void eulerCircuit(TypeOfVer start) {
    if (edges == 0)
      return;

    for (int i = 0; i < vers; ++i) {
      int degree = 0;
      EdgeNode *p = verList[i].head;
      while (p != NULL) {
        ++degree;
        p = p->next;
      }
      //度数为0或奇数,不存在欧拉回路
      if ((degree == 0) || (degree & 0x1))
        return;
    }

    //找到起始点序号
    int iStart = 0;
    for (iStart = 0; iStart < vers; ++iStart){
      if (verList[iStart].ver == start)
        break;
    }
    if (iStart == vers)
      return;

    //保存一个备份
    VerNode *tmp = clone();

    //找到第一条路径(起点所有的边已被访问)
    EulerNode *beg, *end;
    eulerCircuitCore(iStart, beg, end);

    EulerNode *p, *pre;
    while (true) {
      pre = beg;
      p = beg->next;
      while (p != NULL) {
        if (verList[p->nodeNum].head != NULL)
          break;
        pre = p;
        p = p->next;
      }
      if (p == NULL)
        break;

      //从某一个未访问的边开始找一条路径
      EulerNode *begTmp, *endTmp;
      eulerCircuitCore(p->nodeNum, begTmp, endTmp);
      pre->next = begTmp;
      endTmp->next = p->next;
      delete p;
    }

    //恢复原图
    delete [] verList;
    verList = tmp;

    p = beg;
    while (p != NULL) {
      cout << verList[p->nodeNum].ver << '\t';
      pre = p;
      p = p->next;
      delete pre;
    }
    cout << endl;
  }

  //拓扑排序
  void topologySort() const {
    //计算入度
    int *inDegree = new int[vers];
    memset(inDegree, 0, vers * sizeof(int));
    for (int i = 0; i < vers; ++i){
      EdgeNode *p = verList[i].head;
      while (p != NULL) {
        ++inDegree[p->end];
        p = p->next;
      }
    }

    //入度为0的放入队列
    queue<int> q;
    for (int i = 0; i < vers; ++i){
      if (inDegree[i] == 0)
        q.push(i);
    }

    while (!q.empty()) {
      int v = q.front();
      q.pop();
      cout << verList[v].ver << '\t';

      //入度减1, 为0的放入队列
      EdgeNode *p = verList[v].head;
      while (p != NULL) {
        --inDegree[p->end];
        if (inDegree[p->end] == 0) {
          q.push(p->end);
        }
        p = p->next;
      }
    }
    cout << endl;
  }

  //kruskal算法求最小生成树( 时间复杂度O(|E|log|E|) )
  void kruskal() const {
    priority_queue<Edge, deque<Edge>, greater<Edge>> pq;  //最小堆
    //priority_queue<Edge, deque<Edge>, compEdgeGreater> pq;  //最小堆
    //priority_queue<Edge> pq;  //默认最大堆
    DisjointSet ds(vers);

    //所有边放入优先级队列
    for (int i = 0; i < vers; ++i) {
      EdgeNode *p = verList[i].head;
      while (p != NULL) {
        if (i < p->end) { //只添加一次
          Edge edge(i, p->end, p->weight);
          pq.push(edge);
        }
        p = p->next;
      }
    }

    //合并生成最小生成树
    int count = 0;
    while (count < vers - 1) {
      Edge edge = pq.top();
      pq.pop();
      int u = ds.find(edge.beg);
      int v = ds.find(edge.end);
      if (u != v) {
        ++count;
        ds.unionTwoSet(u, v);
        cout << "(" << verList[edge.beg].ver << "," << verList[edge.end].ver << ")\t";
      }
    }
    cout << endl;
  }

  //prim算法求最小生成树( 时间复杂度O(|V^2|) )
  void prim(TypeOfEdge noEdge) const {
    //顶点集合V, 最小生成树结点集合U, 剩余结点V-U
    bool *flag = new bool[vers];                //结点在U中为true
    TypeOfEdge *lowCost = new TypeOfEdge[vers]; //U中结点到结点i的最小权值, 当i在U中时lowCost为noEdge, 当i在V-U中时lowCost为有限值
    int *startNode = new int[vers];             //U中结点startNode[i]到结点i的权值是lowCost[i]

    for (int i = 0; i < vers; ++i) {
      flag[i] = false;
      lowCost[i] = noEdge;
    }

    int start = 0;  //起始点
    int current = start;  //current是即将加入到U中的结点
    for (int i = 1; i < vers; ++i) {
      EdgeNode *p = verList[current].head;
      while (p != NULL) {
        if (!flag[p->end] && p->weight < lowCost[p->end]) { //结点p->end不在U中, 并且结点p->end到结点current的距离小于结点p->end到U中已有点的最小距离
          lowCost[p->end] = p->weight;
          startNode[p->end] = current;
        }
        p = p->next;
      }

      //current加入U
      flag[current] = true;

      //寻找V-U中到V-U的最小距离点
      TypeOfEdge min = noEdge;
      bool tflag = false;
      for (int j = 0; j < vers; ++j) {
        if (lowCost[j] < min) {
          min = lowCost[j];
#if 1
          current = j;  //取V-U中到U的最小距离点作为下一个计算点
#else
          if (!tflag) {
            tflag = true;
            current = j;  //在V-U中随意取一个点,与上面的方法结果一致
          }
#endif
        }
      }
      cout << "(" << verList[startNode[current]].ver << "," << verList[current].ver << ")\t";

      lowCost[current] = noEdge;
    }
    cout << endl;

    delete [] flag;
    delete [] lowCost;
    delete [] startNode;
  }

  //非加权图的单源最短路径( bfs算法, 时间复杂度为|V|和|E|中的较小者, 即O(|V| + |E|) )
  void unweightedShortDistance(TypeOfVer start, TypeOfEdge noEdge) const {
    //找到起始点序号
    int iStart = 0;
    for (iStart = 0; iStart < vers; ++iStart) {
      if (verList[iStart].ver == start)
        break;
    }
    if (iStart == vers)
      return;
    
    TypeOfEdge *distance = new TypeOfEdge[vers];
    int *prev = new int[vers];
    for (int i = 0; i < vers; ++i) {
      distance[i] = noEdge;
    }

    distance[iStart] = 0;
    prev[iStart] = iStart;
    queue<int> q;
    q.push(iStart);
    while (!q.empty()) {
      int u = q.front();
      q.pop();
      EdgeNode *p = verList[u].head;
      while (p != NULL) {
        if (distance[p->end] == noEdge) {
          distance[p->end] = distance[u] + 1;
          prev[p->end] = u;
          q.push(p->end);
        }
        p = p->next;
      }
    }

    for (int i = 0; i < vers; ++i) {
      cout << "the path from " << start << " to "  << verList[i].ver << ": ";
      printPath(iStart, i, prev);
      cout << endl;
    }
    cout << endl;

    delete [] distance;
    delete [] prev;
  }

  //加权图的单源最短路径(dijkstra算法与prim算法有些类似, 时间复杂度O(|V^2|) )
  void dijkstra(TypeOfVer start, TypeOfEdge noEdge) const {
    //找到起始点序号
    int iStart = 0;
    for (iStart = 0; iStart < vers; ++iStart) {
      if (verList[iStart].ver == start)
        break;
    }
    if (iStart == vers)
      return;

    //顶点集合V, 已经找到最短路径的顶点集合U, 剩余结点V-U
    TypeOfEdge *distance = new TypeOfEdge[vers];  //结点i到起始点的最短距离
    bool *konwn = new bool[vers];                 //结点在U中为true
    int *prev = new int[vers];                    //结点i的前继结点
    for (int i = 0; i < vers; ++i) {
      distance[i] = noEdge;
      konwn[i] = false;
    }

    distance[iStart] = 0;
    prev[iStart] = iStart;
    int current = iStart;
    for (int i = 1; i < vers; ++i) {
      //寻找V-U中到U中的最小距离点
      TypeOfEdge min = noEdge;
      for (int j = 0; j < vers; ++j) {
        if (!konwn[j] && distance[j] < min) {
          min = distance[j];
          current = j;
        }
      }

      konwn[current] = true;
      EdgeNode *p = verList[current].head;
      while (p != NULL) {
        if (!konwn[p->end] && min + p->weight < distance[p->end]) {
          distance[p->end] = min + p->weight;
          prev[p->end] = current;
        }
        p = p->next;
      }
    }

    for (int i = 0; i < vers; ++i) {
      cout << "the path from " << start << " to "  << verList[i].ver << ": ";
      printPath(iStart, i, prev);
      cout << "\twith length: " << distance[i] << endl;
    }
    cout << endl;

    delete [] distance;
    delete [] prev;
    delete [] konwn;
  }

  //带负权值图的单源最短路径(可以有环, 但不能有负环, 时间复杂度O(|V||E|) )
  void weightedNegative(TypeOfVer start, TypeOfEdge noEdge) const {
    //找到起始点序号
    int iStart = 0;
    for (iStart = 0; iStart < vers; ++iStart) {
      if (verList[iStart].ver == start)
        break;
    }
    if (iStart == vers)
      return;

    TypeOfEdge *distance = new TypeOfEdge[vers];
    int *prev = new int[vers];
    for (int i = 0; i < vers; ++i) {
      distance[i] = noEdge;
    }

    distance[iStart] = 0;
    prev[iStart] = iStart;
    queue<int> q;
    q.push(iStart);
    while (!q.empty()) {
      int u = q.front();
      q.pop();
      EdgeNode *p = verList[u].head;
      while (p != NULL) {
        if (distance[u] + p->weight < distance[p->end]) {
          distance[p->end] = distance[u] + p->weight;
          prev[p->end] = u;
          q.push(p->end);
        }
        p = p->next;
      }
    }

    for (int i = 0; i < vers; ++i) {
      cout << "the path from " << start << " to "  << verList[i].ver << ": ";
      printPath(iStart, i, prev);
      cout << "\twith length: " << distance[i] << endl;
    }
    cout << endl;

    delete [] distance;
    delete [] prev;
  }

private:
  struct EdgeNode {
    int end;
    TypeOfEdge weight;
    EdgeNode *next;

    EdgeNode(int e, TypeOfEdge w, EdgeNode *n = NULL):end(e), weight(w), next(n) {}
  };

  struct VerNode {
    TypeOfVer ver;
    EdgeNode *head;

    VerNode(EdgeNode *h = NULL):head(h){}
    VerNode(TypeOfVer v, EdgeNode *h = NULL):ver(v), head(h){}
  };

  VerNode *verList;
  bool isWeighted;
  bool isDirected;

  void dfsCore(int start, bool *visited) const {
    cout << verList[start].ver << '\t';
    visited[start] = true;

    EdgeNode *p = verList[start].head;
    while (p != NULL) {
      if (!visited[p->end])
        dfsCore(p->end, visited);
      p = p->next;
    }
  }

  struct EulerNode {
    int nodeNum;
    EulerNode *next;

    EulerNode(int num, EulerNode *n = NULL):nodeNum(num), next(n) {}
  };

  VerNode *clone() const {
    VerNode *tmp = new VerNode[vers];
    for (int i = 0; i < vers; ++i){
      tmp[i].ver = verList[i].ver;
      EdgeNode *p = verList[i].head;
      while (p != NULL) {
        tmp[i].head = new EdgeNode(p->end, p->weight, tmp[i].head);
        p = p->next;
      }
    }
    return tmp;
  }

  void eulerCircuitCore(int start, EulerNode *&beg, EulerNode *&end) {
    beg = end = new EulerNode(start);
    while (verList[start].head != NULL) {
      int nextNodeNum = verList[start].head->end;
      remove(start, nextNodeNum);
      //remove(nextNodeNum, start);

      end->next = new EulerNode(nextNodeNum);
      end = end->next;

      start = nextNodeNum;
    }
  }

  struct Edge {
    int beg, end;
    TypeOfEdge weight;

    Edge(int b, int e, TypeOfEdge w):beg(b), end(e),weight(w) {}
    bool operator>(const Edge &right) const {
      return weight > right.weight;
    }
  };

  struct compEdgeGreater {
    bool operator()(Edge first, Edge second) {
      return first.weight > second.weight;
    }
  };

  void printPath(int start, int end, int *prev) const {
    if (start == end) {
      cout << verList[start].ver;
      return;
    }
    printPath(start, prev[end], prev);
    cout << "-" << verList[end].ver;
  }
};

//有向加权图的邻接矩阵实现
//作为无权图使用时,可将weight置1,权值一样
//作为无向图使用时,插入和删除时需将两个方向的边均插入或删除,修改weight时同样
template <class TypeOfVer, class TypeOfEdge>
class AdjMatrixGraph : public Graph<TypeOfEdge>{
public:
  //这里为了方便,所有成员函数写成内联函数的形式
  AdjMatrixGraph(int v, const TypeOfVer *d, TypeOfEdge noEdgeFlag, bool isWeightedFlag, bool isDirectedFlag) {
    vers = v;
    edges = 0;
    noEdge = noEdgeFlag;
    isWeighted = isWeightedFlag;
    isDirected = isDirectedFlag;

    ver = new TypeOfVer[vers];
    for (int i = 0; i < vers; ++i) {
      ver[i] = d[i];
    }

    edge = new TypeOfEdge *[vers];
    for (int i = 0; i < vers; ++i) {
      edge[i] = new TypeOfEdge[vers];
      for (int j = 0; j < vers; ++j) {
        edge[i][j] = noEdge;
      }
      edge[i][i] = 0;
    }
  }

  ~AdjMatrixGraph() {
    delete [] ver;
    for (int i = 0; i < vers; ++i) {
      delete [] edge[i];
    }
    delete [] edge;
  }

  bool insert(int u, int v, TypeOfEdge w) {
    if (u < 0 || u > vers - 1 || v < 0 || v > vers - 1)
      return false;
    if (exist(u, v))
      return false;
    edge[u][v] = w;
    if (!isDirected)
      edge[v][u] = w;
    ++edges;
    return true;
  }

  bool remove(int u, int v) {
    if (u < 0 || u > vers - 1 || v < 0 || v > vers - 1)
      return false;
    if (!exist(u, v))
      return false;
    edge[u][v] = noEdge;
    if (!isDirected)
      edge[v][u] = noEdge;
    --edges;
    return true;
  }

  bool modify(int u, int v, TypeOfEdge w) {
    if (u < 0 || u > vers - 1 || v < 0 || v > vers - 1)
      return false;
    if (!exist(u, v))
      return false;
    edge[u][v] = w;
    if (!isDirected)
      edge[v][u] = w;
    return true;
  }

  bool exist(int u, int v) const {
    if (u < 0 || u > vers - 1 || v < 0 || v > vers - 1)
      return false;
    if (edge[u][v] == noEdge)
      return false;
    return true;
  }

  //所有顶点对的最短路径( 时间复杂度O(|V^3|) )
  void floyd() const {
    TypeOfEdge **d = new TypeOfEdge *[vers];
    int **prev = new int *[vers];
    for (int i = 0; i < vers; ++i) {
      d[i] = new TypeOfEdge[vers];
      prev[i] = new int[vers];
      for (int j = 0; j < vers; ++j) {
        d[i][j] = edge[i][j];
        prev[i][j] = (edge[i][j] != noEdge) ? i : -1;
      }
    }
    
    for (int k = 0; k < vers; ++k) {
      for (int i = 0; i < vers; ++i) {
        for (int j = 0; j < vers; ++j) {
          if (d[i][k] + d[k][j] < d[i][j]) {
            d[i][j] = d[i][k] + d[k][j];
            prev[i][j] = prev[k][j];
          }
        }
      }
    }

    for (int i = 0; i < vers; ++i) {
      for (int j = 0; j < vers; ++j) {
        cout << "the path from " << ver[i] << " to " << ver[j] << ": ";
        printPath(i, j, prev);
        cout << "\twith length: " << d[i][j]<< endl;
      }
    }
    //cout << "最短路径" << endl;
    //for (int i = 0; i < vers; ++i) {
    //  for (int j = 0; j < vers; ++j) {
    //    cout << prev[i][j] << "\t";
    //  }
    //  cout << endl;
    //}
    //cout << "长度" << endl;
    //for (int i = 0; i < vers; ++i) {
    //  for (int j = 0; j < vers; ++j) {
    //    cout << d[i][j] << "\t";
    //  }
    //  cout << endl;
    //}
    cout << endl;

    delete [] d;
    delete [] prev;
  }

private:
  TypeOfEdge **edge;
  TypeOfVer *ver;
  TypeOfEdge noEdge;
  bool isWeighted;
  bool isDirected;

  void printPath(int start, int end, int **prev) const {
    if (start == end) {
      cout << ver[start];
      return;
    }
    printPath(start, prev[start][end], prev);
    cout << "-" << ver[end];
  }
};

//不相交集(并查集)
class DisjointSet {
public:
  DisjointSet(int n) {
    size = n;
    parent = new int[n];
    for (int i = 0; i < n; ++i) {
      parent[i] = -1;
    }
  }

  ~DisjointSet(){
    delete [] parent;
  }

  int find(int x) {
    if (parent[x] < 0)
      return x;
    return parent[x] = find(parent[x]);
  }

  void unionTwoSet(int root1, int root2){
    if (root1 == root2)
      return;
    if (parent[root1] > parent[root2]) {  //root1规模小
      parent[root2] += parent[root1];
      parent[root1] = root2;
    }
    else{
      parent[root1] += parent[root2];
      parent[root2] = root1;
    }
  }

private:
  int size;
  int *parent;
};


#endif


main.cpp

#include "graph.h"
#include <iostream>
using namespace std;

int main() {
  //有向图的遍历
  cout << "有向图的遍历:" << endl;
  AdjListGraph<char, int> g(7, "0123456", true, true);
  //adjListGraph<char, int> g(7, "1234567", true, true);
  //adjListGraph<char, int> g(7, "abcdefg", true, true);
  g.insert(4, 5, 1);
  g.insert(4, 6, 1);
  g.insert(6, 5, 1);
  g.insert(5, 1, 1);
  g.insert(6, 3, 1);
  g.insert(1, 3, 1);
  g.insert(0, 1, 1);
  g.insert(3, 2, 1);
  g.insert(1, 2, 1);
  g.insert(3, 0, 1);
  g.insert(2, 0, 1);
  g.dfs();
  cout << endl;
  g.dfs(4);
  cout << endl;
  g.bfs();
  cout << endl;
  g.bfs(4);
  cout << endl;
  
  
  //无向图的欧拉回路
  cout << "无向图的欧拉回路:" << endl;
  AdjListGraph<char, int> eulerGraph(6, "012345", true, false);
  eulerGraph.insert(0, 1, 1);
  eulerGraph.insert(0, 2, 1);
  eulerGraph.insert(1, 2, 1);
  eulerGraph.insert(2, 3, 1);
  eulerGraph.insert(1, 4, 1);
  eulerGraph.insert(1, 3, 1);
  eulerGraph.insert(2, 4, 1);
  eulerGraph.insert(3, 4, 1);
  eulerGraph.insert(3, 5, 1);
  eulerGraph.insert(4, 5, 1);
  eulerGraph.eulerCircuit('5');
  

  //有向无环图的拓扑排序
  cout << "有向无环图的拓扑排序:" << endl;
  AdjListGraph<char, int> topologyGraph(7, "0123456", true, true);
  topologyGraph.insert(0, 1, 1);
  topologyGraph.insert(0, 2, 1);
  topologyGraph.insert(1, 3, 1);
  topologyGraph.insert(1, 4, 1);
  topologyGraph.insert(1, 5, 1);
  topologyGraph.insert(2, 4, 1);
  topologyGraph.insert(2, 6, 1);
  topologyGraph.insert(4, 5, 1);
  topologyGraph.insert(4, 6, 1);
  topologyGraph.insert(5, 3, 1);
  topologyGraph.topologySort();

  //无向图的最小生成树
  cout << "最小生成树:" << endl;
  //AdjListGraph<char, int> minimumSpanningTree(6, "012345", true, false);
  AdjListGraph<char, int> minimumSpanningTree(6, "123456", true, false);
  minimumSpanningTree.insert(0, 3, 5);
  minimumSpanningTree.insert(3, 5, 2);
  minimumSpanningTree.insert(4, 5, 6);
  minimumSpanningTree.insert(1, 4, 3);
  minimumSpanningTree.insert(0, 1, 6);
  minimumSpanningTree.insert(0, 2, 1);
  minimumSpanningTree.insert(1, 2, 5);
  minimumSpanningTree.insert(2, 3, 5);
  minimumSpanningTree.insert(2, 4, 6);
  minimumSpanningTree.insert(2, 5, 4);
  minimumSpanningTree.kruskal();
  minimumSpanningTree.prim(INT_MAX);

  //有向图的单源最短路径
  cout << "单源最短路径:" << endl;
  AdjListGraph<char, int> singleSourceShortestPath(7, "0123456", true, true);
  singleSourceShortestPath.insert(0, 1, 2);
  singleSourceShortestPath.insert(1, 4, 10);
  singleSourceShortestPath.insert(4, 6, 6);
  singleSourceShortestPath.insert(6, 5, 1);
  singleSourceShortestPath.insert(2, 0, 4);
  singleSourceShortestPath.insert(2, 5, 5);
  singleSourceShortestPath.insert(0, 3, 1);
  singleSourceShortestPath.insert(1, 3, 3);
  singleSourceShortestPath.insert(3, 2, 2);
  singleSourceShortestPath.insert(3, 4, 2);
  singleSourceShortestPath.insert(3, 5, 8);
  singleSourceShortestPath.insert(3, 6, 4);
  cout << "非加权图" << endl;
  singleSourceShortestPath.unweightedShortDistance('2', INT_MAX);
  cout << "加权图" << endl;
  //singleSourceShortestPath.dijkstra('1', INT_MAX);
  singleSourceShortestPath.dijkstra('2', INT_MAX);

  //有向带负权值图的单源最短路径
  AdjListGraph<char, int> singleSourceShortestPathWeightedNegative(7, "0123456", true, true);
  singleSourceShortestPathWeightedNegative.insert(0, 1, 2);
  singleSourceShortestPathWeightedNegative.insert(1, 4, 10);
  singleSourceShortestPathWeightedNegative.insert(4, 6, 6);
  singleSourceShortestPathWeightedNegative.insert(6, 5, 1);
  singleSourceShortestPathWeightedNegative.insert(2, 0, 4);
  singleSourceShortestPathWeightedNegative.insert(2, 5, 3);
  singleSourceShortestPathWeightedNegative.insert(0, 3, 1);
  singleSourceShortestPathWeightedNegative.insert(1, 3, 3);
  singleSourceShortestPathWeightedNegative.insert(3, 2, 2);
  singleSourceShortestPathWeightedNegative.insert(3, 4, 2);
  singleSourceShortestPathWeightedNegative.insert(3, 5, -8);
  singleSourceShortestPathWeightedNegative.insert(3, 6, 4);
  cout << "带负权值图" << endl;
  singleSourceShortestPathWeightedNegative.weightedNegative('2', INT_MAX);

  //有向图所有顶点对的最短路径
  cout << "所有顶点对的最短路径:" << endl;
  AdjMatrixGraph<char, int> allVertexPairShortestPath(3, "012", INT_MAX, true, true);
  allVertexPairShortestPath.insert(0, 1, 8);
  allVertexPairShortestPath.insert(1, 0, 3);
  allVertexPairShortestPath.insert(0, 2, 5);
  allVertexPairShortestPath.insert(2, 0, 6);
  allVertexPairShortestPath.insert(2, 1, 2);
  allVertexPairShortestPath.floyd();

  int ttt = 0;
  return 0;
}






  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值