程序设计代码 贴着玩。。七

图类的实现


两种存储结构的邻接矩阵和邻接链表存储的都实现了,实现了图类的大部分算法

#ifndef GRAPH_H_INCLUDED
#define GRAPH_H_INCLUDED
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<stack>
#include<cstring>
#include<string>
#include<queue>
const int MAX_V = 100;///图最多有一百个顶点
const int MAX_W = 1000;///边的权重最多为1000
class Graph{
public:

    ///I. 构造函数与析构函数
	Graph( ) {}
	virtual ~Graph( ) {}
    ///II. 图的维护函数
   virtual int GraphEmpty(void) const = 0; ///检测图是否为空
	virtual int GraphFull(void) const = 0;; ///检测图是否已满,即顶点个数是否越界
	virtual int NumberOfVertices( void ) const = 0;///返回图的顶点个数
	virtual int NumberOfEdges( void ) const = 0; ///返回图的边个数
   virtual int GetWeight( const int v1, const int v2 ) = 0; /// 返回指定边的权值
	virtual int* GetNeighbors( const int v ) = 0;/// 返回顶点v的邻接顶点表
   virtual int GetFirstNeighbor( const int v ) = 0; /// 返回序号为v的顶点的第一个邻接顶点的序号
   virtual int GetNextNeighbor( const int v1, const int v2 ) = 0; ///返回序号为v1的顶点相对于序号为v2的顶点的下一个邻接顶点的序号
	virtual void InsertVertex( const int & v) = 0; /// 向图中插入一个顶点
	virtual void InsertEdge(const int & v1, const int & v2, int weight) = 0; ///向图中插入一条边
	virtual void DeleteVertex( const int & v ) = 0; ///从图中删除一个顶点
	virtual void DeleteEdge( const int & v1, const int & v2 ) = 0; ///从图中删除一条边

   /// III. 图的基本算法
   virtual void DepthFirstSearch() = 0;///图的深度优先搜索(递归)
   virtual void RDFS(int u, int visited[]) = 0;
   virtual void DFS(const int v) = 0; ///从顶点v开始进行图的深度优先搜索(迭代方法)
   virtual void BFS( const int v ) = 0; ///从顶点v开始进行图的广度优先搜索
   virtual void TopoOrder( ) = 0; /// 图的拓扑排序
   virtual void CriticalPath( ) = 0; /// 输出图的关键路径
   virtual void ShortestPath(const int v ) = 0; /// 求无权图中顶点v到其他顶点的最短路径
   virtual void DShortestPath(const int v ) = 0; /// 求正权图中顶点v到其他顶点的最短路径
   virtual void AllLength( ) = 0; /// 求正权图中每对顶点间的最短路径
   virtual void Prim(int u0 ) = 0; /// 构造图的最小支撑树的普里姆算法
};

class Graph_Matrix:public Graph{
private:
   int num_v;///顶点个数
   int num_e;///边的个数
   int Edge[MAX_V][MAX_V];
public:
    ///II. 图的维护函数
   Graph_Matrix(FILE *fp);
   virtual int GraphEmpty(void) const; ///检测图是否为空
	virtual int GraphFull(void) const ; ///检测图是否已满,即顶点个数是否越界
	virtual int NumberOfVertices( void ) const ;///返回图的顶点个数
	virtual int NumberOfEdges( void ) const ; ///返回图的边个数
   virtual int GetWeight( const int v1, const int v2 ) ; /// 返回指定边的权值
	virtual int* GetNeighbors( const int v ) ;/// 返回顶点v的邻接顶点表
   virtual int GetFirstNeighbor( const int v ) ; /// 返回序号为v的顶点的第一个邻接顶点的序号
   virtual int GetNextNeighbor( const int v1, const int v2 ) ; ///返回序号为v1的顶点相对于序号为v2的顶点的下一个邻接顶点的序号
	virtual void InsertVertex( const int & v) ; /// 向图中插入一个顶点
	virtual void InsertEdge(const int & v1, const int & v2, int weight);
	virtual void DeleteVertex( const int & v ) ; ///从图中删除一个顶点
	virtual void DeleteEdge( const int & v1, const int & v2 ) ; ///从图中删除一条边

   /// III. 图的基本算法
   virtual void DepthFirstSearch() ;///图的深度优先搜索(递归)
   virtual void RDFS(int u, int visited[]);
   virtual void DFS(const int v) ; ///从顶点v开始进行图的深度优先搜索(迭代方法)
   virtual void BFS( const int v ) ; ///从顶点v开始进行图的广度优先搜索
   virtual void TopoOrder( ) ; /// 图的拓扑排序
   virtual void CriticalPath( ) ; /// 输出图的关键路径
   virtual void ShortestPath(const int v ) ; /// 求无权图中顶点v到其他顶点的最短路径
   virtual void DShortestPath(const int v ) ; /// 求正权图中顶点v到其他顶点的最短路径
   virtual void AllLength( ) ; /// 求正权图中每对顶点间的最短路径
   virtual void Prim(int u0 ) ; /// 构造图的最小支撑树的普里姆算法
};

struct Edge{
   int VerAdj;///边的另一个结点的边号
   int weight;///边的权值
   Edge *next;///下一个边结点的指针
};

struct Vertex{
   int num;///顶点的编号
   Edge *head1;///出边链表的头指针
   Edge *head2;///入边链表的头指针
};


class Graph_Link:public Graph{
private:
   int num_v, num_e;
   Vertex Head[MAX_V];
public:
   Graph_Link(FILE *fp);
    ///II. 图的维护函数
   virtual int GraphEmpty(void) const ;///检测图是否为空
	virtual int GraphFull(void) const ; ///检测图是否已满,即顶点个数是否越界
	virtual int NumberOfVertices( void ) const ;///返回图的顶点个数
	virtual int NumberOfEdges( void ) const ; ///返回图的边个数
   virtual int GetWeight( const int v1, const int v2 ) ; /// 返回指定边的权值
	virtual int* GetNeighbors( const int v ) ;/// 返回顶点v的邻接顶点表
   virtual int GetFirstNeighbor( const int v ) ; /// 返回序号为v的顶点的第一个邻接顶点的序号
   virtual int GetNextNeighbor( const int v1, const int v2 ) ; ///返回序号为v1的顶点相对于序号为v2的顶点的下一个邻接顶点的序号
	virtual void InsertVertex( const int & v) ; /// 向图中插入一个顶点
	virtual void InsertEdge(const int& v1, const int& v2, int weight);///想图中加入一条边
	virtual void DeleteVertex( const int & v ) ; ///从图中删除一个顶点
	virtual void DeleteEdge( const int & v1, const int & v2 ) ; ///从图中删除一条边

   /// III. 图的基本算法
   virtual void DepthFirstSearch() ;///图的深度优先搜索(递归)
   virtual void RDFS(int u, int visited[]);
   virtual void DFS(const int v) ; ///从顶点v开始进行图的深度优先搜索(迭代方法)
   virtual void BFS( const int v ) ; ///从顶点v开始进行图的广度优先搜索
   virtual void TopoOrder( ) ; /// 图的拓扑排序
   virtual void CriticalPath( ) ; /// 输出图的关键路径
   virtual void ShortestPath(const int v ) ; /// 求无权图中顶点v到其他顶点的最短路径
   virtual void DShortestPath(const int v ) ; /// 求正权图中顶点v到其他顶点的最短路径
   virtual void AllLength( ) ; /// 求正权图中每对顶点间的最短路径
   virtual void Prim( int u0) ; /// 构造图的最小支撑树的普里姆算法
};
#endif // GRAPH_H_INCLUDED

#include"Graph.h"
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
#include<stack>
#include<queue>
using namespace std;

Graph_Matrix::Graph_Matrix(FILE *fp) {
   printf("请输入所构造图的顶点个数以及边的个数\n");
   int v, e;
   fscanf(fp, "%d%d", &v, &e);
   num_v = v;
   num_e = e;
   printf("请输入所要构造的图的边的信息\n");
   for(int i = 0; i < v; ++ i) {
      for(int j = 0; j < v; ++ j) {
         if(i == j) {
            Edge[i][j] = 0;
         } else {
            Edge[i][j] = MAX_W;
         }
      }
   }
   int f, t, w;
   for(int i = 0; i < e; ++ i) {
      fscanf(fp, "%d %d %d", &f, &t, &w);
      Edge[f][t] = w;
   }
}

int Graph_Matrix::GraphEmpty(void) const{
   if(num_v == 0) {
      return 1;
   }
   return 0;
}

int Graph_Matrix::GraphFull(void) const{
   if(num_v == MAX_V) {
      return 1;
   }
   return 0;
}

int Graph_Matrix::NumberOfVertices(void) const {
   return num_v;
}

int Graph_Matrix::NumberOfEdges() const {
   return num_e;
}

int Graph_Matrix::GetWeight(const int v1, const int v2) {
   return Edge[v1][v2];
}

int* Graph_Matrix::GetNeighbors(const int v) {
   int cnt = 0;
   int neighbor[num_v];
   memset(neighbor, -1, sizeof(neighbor));
   for(int i = 0; i < num_v; ++ i) {
      if(Edge[v][i] != 0) {
         neighbor[cnt++] = i;
      }
   }
   return neighbor;
}

int Graph_Matrix::GetFirstNeighbor(const int v) {
   int cnt = 0;
   for(int i = 0; i < num_v; ++ i) {
      if(Edge[v][i] != 0) {
         return i;
      }
   }
   return -1;
}

int Graph_Matrix::GetNextNeighbor(const int v1, const int v2) {
   for(int i = 0; i < num_v; ++ i) {
      if(i != v2 && Edge[v1][i] != MAX_W) {
         return i;
      }
   }
   return -1;
}

void Graph_Matrix::InsertVertex(const int& v) {
   if(GraphFull()) {
      cout<<"图已满,无法再插入"<<endl;
      return ;
   }
   num_v++;
}

void Graph_Matrix::InsertEdge(const int& v1, const int& v2, int weight) {
   Edge[v1][v2] = weight;
}

void Graph_Matrix::DeleteVertex(const int& v) {
   for(int i = 0; i < num_v; ++ i) {
      Edge[i][v] = Edge[v][i] = MAX_W;
   }
   num_v--;
}

void Graph_Matrix::DeleteEdge(const int& v1, const int& v2) {
   Edge[v1][v2] = MAX_W;
}

void Graph_Matrix::RDFS(int u, int visited[]) {
   for(int i = 1; i < num_v; ++ i) {
      if(!visited[i] && Edge[u][i] < MAX_W) {
         visited[i] = 1;
         cout<<" "<<i;
         RDFS(i, visited);
      }
   }
}

void Graph_Matrix::DepthFirstSearch() {
   int visited[num_v];
   memset(visited, 0, sizeof(visited));
   visited[0] = 1;
   cout<<0;
   RDFS(0, visited);
   cout<<endl;
}

void Graph_Matrix::DFS(int v) {
   stack<int>s;
   int visited[num_v];
   for(int i = 0; i < num_v; ++ i) {
      visited[i] = 0;
   }
   s.push(v);
   visited[v] = 1;
   while(!s.empty()) {
      int t = s.top();
      cout<<t<<" ";
      s.pop();
      for(int i = 0; i < num_v; ++ i) {
         if(Edge[t][i] != MAX_W && !visited[i]) {
            s.push(i);
            visited[i] = 1;
         }
      }
   }
   cout<<endl;
}

void Graph_Matrix::BFS(int v) {
   queue<int>q;
   q.push(v);
   int visited[num_v];
   for(int i = 0; i < num_v; ++ i) {
      visited[i] = 0;
   }
   visited[v] = 1;
   while(!q.empty()) {
      int f = q.front();
      cout<<f<<" ";
      q.pop();
      for(int i = 0; i < num_v; ++ i) {
         if(Edge[f][i] != 0 && !visited[i]) {
            q.push(i);
            visited[i] = 1;
         }
      }
   }
   cout<<endl;
}

void Graph_Matrix::TopoOrder() {
   int indeg[num_v];
   memset(indeg, 0, sizeof(indeg));
   for(int i = 0; i < num_v; ++ i) {
      for(int j = 0; j < num_v; ++ j) {
         if(i != j && Edge[j][i] != MAX_W) {
            indeg[i]++;
         }
      }
      //cout<<indeg[i]<<" ";
   }
   cout<<endl;
   int top = 0;
   stack<int>s;
   int visited[num_v];
   memset(visited, 0, sizeof(visited));
   for(int i = 0; i < num_v; ++ i) {
      if(indeg[i] == 0) {
         s.push(i);
         visited[i] = 1;
      }
   }
   while(!s.empty()) {
      int j = s.top();
      s.pop();
      cout<<j<<" ";
      top++;
      for(int k = 0; k < num_v; ++ k) {
         if(Edge[j][k] != MAX_W) {
            indeg[k]--;
            if(indeg[k] == 0 && !visited[k]) {
               s.push(k);
               visited[k] = 1;
            }
         }
      }
   }
   if(top != num_v) {
      printf("图中存在环\n");
   } else {
      printf("\n拓扑排序完成");
   }
}

void Graph_Matrix::CriticalPath() {
   int topoorder[num_v];
   int indeg[num_v];
   int ve[num_v];
   int vl[num_v];
   memset(indeg, 0, sizeof(indeg));
   for(int i = 0; i < num_v; ++ i) {
      for(int j = 0; j < num_v; ++ j) {
         if(i != j && Edge[j][i] != MAX_W) {
            indeg[i]++;
         }
      }
   }
   int top = 0;
   stack<int>s;
   int visited[num_v];
   memset(visited, 0, sizeof(visited));
   for(int i = 0; i < num_v; ++ i) {
      if(indeg[i] == 0) {
         s.push(i);
         visited[i] = 1;
      }
   }
   while(!s.empty()) {
      int j = s.top();
      s.pop();
      topoorder[top] = j;
      top++;
      for(int k = 0; k < num_v; ++ k) {
         if(Edge[j][k] != MAX_W) {
            indeg[k]--;
            if(indeg[k] == 0 && !visited[k]) {
               s.push(k);
               visited[k] = 1;
            }
         }
      }
   }
   if(top != num_v) {
      printf("图中存在环无法寻找关键路径");
      return;
   }
   ve[topoorder[0]] = 0;
   for(int i = 1; i < num_v; ++ i) {
      int max = 0, temp;
      for(int j = 0; j < i; ++ j) {
         if(Edge[topoorder[j]][topoorder[i]] != MAX_W) {
            temp = ve[topoorder[j]] + Edge[topoorder[j]][topoorder[i]];
            if(temp > max) {
               max = temp;
            }
         }
      }
      ve[topoorder[i]] = max;
   }
   vl[topoorder[num_v - 1]] = ve[topoorder[num_v - 1]];
   for(int i = num_v - 2; i >= 0; -- i) {
      int min = vl[topoorder[num_v - 1]], temp;
      for(int j = num_v - 1; j > i; -- j) {
         if(Edge[topoorder[i]][topoorder[j]] != MAX_W) {
            temp = vl[topoorder[j]] - Edge[topoorder[i]][topoorder[j]];
            if(temp < min) {
               min = temp;
            }
         }
      }
      vl[topoorder[i]] = min;
   }
   for(int i = 0; i < num_v; ++ i) {
      for(int j = i + 1; j < num_v; ++ j) {
         if(Edge[topoorder[i]][topoorder[j]] != MAX_W) {
            if(ve[topoorder[i]] == vl[topoorder[j]] - Edge[topoorder[i]][topoorder[j]]) {
               printf("<%d, %d>是关键路径\n", topoorder[i], topoorder[j]);
            }
         }
      }
   }
}

void Graph_Matrix::ShortestPath(const int v) {
   int dist[num_v];
   int path[num_v];
   for(int i = 0; i < num_v; ++ i) {
      dist[i] = -1;
      path[i] = -1;
   }
   dist[v] = 0;
   queue<int>q;
   q.push(v);
   while(!q.empty()) {
      int f = q.front();
      q.pop();
      for(int i = 0; i < num_v; ++ i) {
         if(dist[i] == -1 && Edge[f][i] != MAX_W) {
            q.push(i);
            dist[i] = dist[f] + 1;
            path[i] = f;
         }
      }
   }
   int result[num_v];
   for(int i = 0; i < num_v; ++ i) {
      if(dist[i] == -1) {
         cout<<"从点"<<v<<"到点"<<i<<"不存在路径"<<endl;
      } else {
         cout<<"从点"<<v<<"到点"<<i<<"的路径长度为:"<<dist[i]<<endl;
         int cnt = 0;
         result[cnt ++ ] = i;
         int a = i;
         while(path[a] != -1) {
            result[cnt++] = path[a];
            a = path[a];
         }
         cout<<"最短路径为";
         for(int i = cnt - 1; i >= 0; -- i) {
            if(i == cnt - 1) {
               printf("%d", result[i]);
            } else {
               printf("->%d", result[i]);
            }
         }
         printf("\n");
      }
   }
}

void Graph_Matrix::DShortestPath(int u) {
   int path[num_v];
   int s[num_v];
   int dist[num_v];
   for(int i = 0; i < num_v; ++ i) {
      dist[i] = Edge[u][i];
      s[i] = 0;
      if(i != u && dist[u] < MAX_W ) {
         path[i] = u;
      } else {
         path[i] = -1;
      }
   }
   s[u] = 1;
   for(int i = 1; i < num_v; ++ i) {
      int min = MAX_W, v = u;
      for(int j = 0; j < num_v; ++ j) {
         if(!s[j] && dist[j] < MAX_W) {
            v = j;
            min = dist[j];
         }
      }
      s[v] = 1;
      for(int j = 0; j < num_v; ++ j) {
         if(!s[j] && Edge[v][j] < MAX_W && dist[v] + Edge[v][j] < dist[j]) {
            dist[j] = dist[v] + Edge[v][j];
            path[j] = v;
         }
      }
   }
   int result[num_v];
   for(int i = 0; i < num_v; ++ i) {
      if(dist[i] == -1) {
         cout<<"从点"<<u<<"到点"<<i<<"不存在路径"<<endl;
      } else {
         cout<<"从点"<<u<<"到点"<<i<<"的加权路径长度为:"<<dist[i]<<endl;
         int cnt = 0;
         int a = i;
         result[cnt ++ ] = i;
         while(path[a] != -1) {
            result[cnt++] = path[a];
            a = path[a];
         }
         cout<<"最短路径为";
         for(int j = cnt - 1; j >= 0; -- j) {
            if(j != cnt - 1) {
               cout<<"->"<<result[j];
            } else {
               cout<<result[j];
            }
         }
         cout<<endl;
      }
   }
}

void Graph_Matrix::AllLength() {
   int floyd[num_v][num_v];
   int path[num_v][num_v];
   for(int i = 0; i < num_v; ++ i) {
      for(int j = 0; j < num_v; ++ j) {
         floyd[i][j] = Edge[i][j];
         if(i != j && floyd[i][j] < MAX_W) {
            path[i][j] = i;
         } else {
            path[i][j] = -1;
         }
      }
   }
   for(int k = 0; k < num_v; ++ k) {
      for(int i = 0; i < num_v; ++ i) {
         if(i != k) {
            for(int j = 0; j < num_v; ++ j) {
               if(j != k && j != i && floyd[i][k] < MAX_W && floyd[k][j] < MAX_W) {
                  if(floyd[i][k] + floyd[k][j] < floyd[i][j]) {
                     floyd[i][j] = floyd[i][k] + floyd[k][j];
                     path[i][j] = path[k][j];
                  }
               }
            }
         }
      }
   }
   for(int i = 0; i < num_v; ++ i)  {
      for(int j = 0; j < num_v; ++ j) {
         if(i == j) {
            continue;
         }
         if(floyd[i][j] < MAX_W ) {
            cout<<"从点"<<i<<"到点"<<j<<"加权最短路径长度为:"<<floyd[i][j]<<endl;
            cout<<"最短路径为:";
            int result[num_v];
            memset(result, 0, sizeof(result));
            int cnt = 0;
            result[cnt] = j;
            while(path[i][result[cnt]] != i) {
               cnt ++ ;
               result[cnt] = path[i][result[cnt - 1]];
            }
            cnt ++ ;
            result[cnt] = i;
            for(int k = cnt; k > 0; -- k) {
               cout<<result[k]<<"->";
            }
            cout<<result[0]<<endl;
         } else {
            cout<<"从点"<<i<<"到点"<<j<<"不存在路径"<<endl;
         }
      }
   }
}

void Graph_Matrix::Prim(int u0) {
   int sumweight = 0;
   int lowcost[num_v];
   int nearvex[num_v];
   for(int i = 0; i < num_v; ++ i) {
      lowcost[i] = Edge[u0][i];
      nearvex[i] = u0;
   }
   nearvex[u0] = -1;
   for(int i = 0; i < num_v; ++ i) {
      int min = MAX_W;
      int v = -1;
      for(int j = 0; j < num_v; ++ j) {
         if(nearvex[j] != -1 && lowcost[j] < min) {
            min = lowcost[j];
            v = j;
         }
      }
      if(v != -1) {
         printf("%d -> %d 这条边被选中,其权值是 %d\n", nearvex[v], v, lowcost[v]);
         nearvex[v] = -1;
         sumweight += lowcost[v];
         for(int j = 0; j < num_v; ++ j) {
            if(nearvex[j] != -1 && Edge[v][j] < lowcost[j]) {
               lowcost[j] = Edge[v][j];
               nearvex[j] = v;
            }
         }
      }
   }
   printf("最小生成树的总权值为:%d\n", sumweight);
}

Graph_Link::Graph_Link(FILE *fp) {
   cout<<"请输入所要构造的图的顶点个数和边的个数"<<endl;
   int n, e;
   fscanf(fp, "%d%d", &n, &e);
   num_v = n;
   num_e = e;
   for(int i = 0; i < n; ++ i) {
      Head[i].head1 = Head[i].head2 = NULL;
   }
   printf("请输入所要构造的图的边的信息\n");
   int u, v, w;
   for(int i = 0; i < e; ++ i) {
      fscanf(fp, "%d %d %d", &u, &v, &w);
      InsertEdge(u, v, w);
   }
}

int Graph_Link::GraphEmpty() const {
   if(num_v == 0) {
      return 1;
   }
   return 0;
}

int Graph_Link::GraphFull() const {
   if(num_v == MAX_V) {
      return 1;
   }
   return 0;
}

int Graph_Link::NumberOfVertices() const {
   return num_v;
}

int  Graph_Link::NumberOfEdges() const {
   return num_e;
}

int Graph_Link::GetWeight(const int u, const int v) {
   Edge *p = Head[u].head1;
   while(p -> next != NULL) {
      p = p -> next;
      if(p -> VerAdj == v) {
         return p -> weight;
      }
   }
   return MAX_W;
}

int* Graph_Link::GetNeighbors(const int u) {
   int neighbor[num_v];
   memset(neighbor, -1, sizeof(neighbor));
   Edge *p = Head[u].head1;
   int cnt = 0;
   while(p -> next != NULL) {
      p = p -> next;
      neighbor[cnt ++] = p -> VerAdj;
   }
   return neighbor;
}

int Graph_Link::GetFirstNeighbor(const int u) {
   if(Head[u].head1->next != NULL) {
      return Head[u].head1->next->VerAdj;
   }
   return -1;
}

int Graph_Link::GetNextNeighbor(const int u, const int v) {
   Edge *p = Head[u].head1;
   while(p -> next != NULL) {
      p = p -> next;
      if(p -> VerAdj == v) {
         p = p -> next;
         if(p == NULL) {
            return -1;
         }
         return p -> VerAdj;
      }
   }
   return -1;
}

void Graph_Link::InsertVertex(const int& v) {
   if(num_v == MAX_V) {
      cout<<"图已满无法插入"<<endl;
      return;
   }
   num_v ++;
}

void Graph_Link::InsertEdge(const int& u, const int& v, int w) {
   Edge *p = new Edge();
   p->VerAdj = v;
   p->weight = w;
   p->next = NULL;
   Edge *q = Head[u].head1;
   //printf("插入");
   if(q == NULL) {
      Head[u].head1 = p;
   } else {
      while(q->next != NULL) {
        // printf("while循环\n");
         q = q->next;
      }
      q->next = p;
   }




   printf("插入成功\n");

}

void Graph_Link::DeleteVertex(const int& v) {
   ///
}

void Graph_Link::DeleteEdge(const int& u, const int& v) {
   Edge *p = Head[u].head1, *temp;
   if(u == v) {
      printf("请输入两个不同的点");
      return;
   }
   while(p != NULL) {
      temp = p;
      if(p -> VerAdj == v) {
         temp -> next = p -> next;
         delete p;
      }
      p = p -> next;
   }
}

void Graph_Link::RDFS(const int v, int visited[]) {
   cout<<v<<" ";
   //visited[v] = 1;
   Edge *p = Head[v].head1;
   while(p != NULL) {
      if(!visited[p->VerAdj]) {
         RDFS(p->VerAdj, visited);
         visited[p->VerAdj] = 1;
      }
      p = p->next;
   }
}

void Graph_Link::DepthFirstSearch() {
   int visited[num_v];
   memset(visited, 0, sizeof(visited));
   visited[0] =1;
   cout<<"深度优先遍历的序列:";
   RDFS(0., visited);
   cout<<endl;
}

void Graph_Link::DFS(int u) {
   int visited[num_v];
   memset(visited, 0, sizeof(visited));
   stack<int>s;
   s.push(u);
   visited[u] = 1;
   int w;
   Edge *p;
   cout<<"深度优先遍历的序列:";
   while(!s.empty()) {
      w = s.top();
      s.pop();
      cout<<w<<" ";
      p = Head[w].head1;
      while(p != NULL) {
         if(!visited[p->VerAdj]) {
            s.push(p->VerAdj);
            visited[p->VerAdj] = 1;
         }
         p = p->next;
      }
   }
   cout<<endl;
}

void Graph_Link::BFS(const int u) {
   int visited[num_v];
   memset(visited, 0, sizeof(visited));
   visited[u] = 1;
   queue<int>q;
   q.push(u);
   int f;
   Edge *p;
   cout<<"宽度优先遍历的序列为:";
   while(!q.empty()) {
      f = q.front();
      q.pop();
      cout<<f<<" ";
      p = Head[f].head1;
      while(p != NULL) {
         if(!visited[p->VerAdj]) {
            visited[p->VerAdj] = 1;
            q.push(p->VerAdj);
         }
         p = p->next;
      }
   }
   cout<<endl;
}

void Graph_Link::TopoOrder() {
   int count[num_v];
   memset(count, 0, sizeof(count));
   for(int i = 0; i < num_v; ++ i) {
      Edge *p = Head[i].head1;
      while(p != NULL) {
         count[p->VerAdj] ++;
         p = p->next;
      }
   }
   stack<int>s;
   int visited[num_v];
   memset(visited, 0, sizeof(visited));
   for(int i = 0; i < num_v; ++ i) {
      if(count[i] == 0) {
         s.push(i);
         visited[i] = 1;
      }
   }
   int cnt = 0, top;
   Edge *p;
   cout<<"拓扑序列为:";
   while(!s.empty()) {
      top = s.top();
      cout<<top<<" ";
      cnt ++;
      s.pop();
      p = Head[top].head1;
      while(p != NULL) {
         if(!visited[p->VerAdj]) {
            count[p->VerAdj]--;
            if(count[p->VerAdj] == 0) {
               s.push(p->VerAdj);
               visited[p->VerAdj] = 1;
            }
         }
         p = p->next;
      }
   }
   if(cnt != num_v) {
      cout<<"图中存在环"<<endl;
   } else {
      cout<<endl;
   }
}

void Graph_Link::CriticalPath() {
   int count[num_v];
   memset(count, 0, sizeof(count));
   for(int i = 0; i < num_v; ++ i) {
      Edge *p = Head[i].head1;
      while(p != NULL) {
         count[p->VerAdj] ++;
         p = p->next;
      }
   }
   stack<int>s;
   int visited[num_v];
   memset(visited, 0, sizeof(visited));
   for(int i = 0; i < num_v; ++ i) {
      if(count[i] == 0) {
         s.push(i);
         visited[i] = 1;
      }
   }
   int cnt = 0, top;
   Edge *p;
   int topoorder[num_v];
   while(!s.empty()) {
      top = s.top();
      topoorder[cnt] = top;
      cnt ++;
      s.pop();
      p = Head[top].head1;
      while(p != NULL) {
         if(!visited[p->VerAdj]) {
            count[p->VerAdj]--;
            if(count[p->VerAdj] == 0) {
               s.push(p->VerAdj);
               visited[p->VerAdj] = 1;
            }
         }
         p = p->next;
      }
   }
   int ve[num_v];
   int vl[num_v];
   memset(ve, 0, sizeof(ve));
   int k;
   for(int i = 0; i < num_v; ++ i) {
      Edge *p = Head[topoorder[i]].head1;
      while(p != NULL) {
         k = p->VerAdj;
         if(ve[topoorder[i]] + p->weight > ve[k]) {
            ve[k] = ve[topoorder[i]] + p->weight;
         }
         p = p->next;
      }
   }
   for(int i = 0; i < num_v; ++ i) {
      vl[i] = ve[topoorder[num_v - 1]];
   }
   for(int i = num_v - 2; i >= 0; -- i) {
      Edge *p = Head[topoorder[i]].head1;
      while(p != NULL) {
         k = p->VerAdj;
         if(vl[k] - p->weight < vl[topoorder[i]]) {
            vl[topoorder[i]] = vl[k] - p->weight;
         }
         p = p->next;
      }
   }
   for(int i = 0; i < num_v; ++ i) {
      Edge *p = Head[i].head1;
      while(p != NULL) {
         k = p->VerAdj;
         if(ve[i] == vl[k] - p->weight) {
            cout<<'<'<<i<<", "<<k<<'>'<<"是关键路径"<<endl;
         }
         p = p->next;
      }
   }
}

void Graph_Link::ShortestPath(const int u) {
   int path[num_v];
   int dist[num_v];
   queue<int>q;
   memset(path, -1, sizeof(path));
   memset(dist, -1, sizeof(dist));
   dist[u] = 0;
   q.push(u);
   int f, k;
   while(!q.empty()) {
      f = q.front();
      q.pop();
      Edge *p = Head[f].head1;
      while(p != NULL) {
         k = p->VerAdj;
         if(dist[k] == -1) {
            q.push(k);
            dist[k] = dist[f] + 1;
            path[k] = f;
         }
         p = p->next;
      }
   }
   int result[num_v];
   for(int i = 0; i < num_v; ++ i) {
      if(dist[i] == -1) {
         cout<<"从点"<<u<<"到点"<<i<<"不存在路径"<<endl;
      } else {
         cout<<"从点"<<u<<"到点"<<i<<"的路径长度为:"<<dist[i]<<endl;
         int cnt = 0;
         result[cnt ++ ] = i;
         int a = i;
         while(path[a] != -1) {
            result[cnt++] = path[a];
            a = path[a];
         }
         cout<<"最短路径为";
         for(int i = cnt - 1; i >= 0; -- i) {
            if(i == cnt - 1) {
               printf("%d", result[i]);
            } else {
               printf("->%d", result[i]);
            }
         }
         printf("\n");
      }
   }
}

void Graph_Link::DShortestPath(const int u) {
   int path[num_v];
   int dist[num_v];
   int s[num_v];
   memset(path, -1, sizeof(path));
   memset(s, 0, sizeof(s));
   memset(dist, -1, sizeof(dist));
   int k;
   Edge *p = NULL;
   p = Head[u].head1;
   while(p != NULL) {
      dist[p->VerAdj] = p->weight;
      path[p->VerAdj] = u;
      p = p->next;
   }
   dist[u] = 0;
   s[u] = 1;
   for(int i = 0; i < num_v; ++ i) {
      int min = MAX_W;
      int v = -1;
      for(int j = 0; j < num_v; ++ j) {
         if(dist[j] > 0 && dist[j] < min && !s[j]) {
            v = j;
            min = dist[j];
         }
      }
      if(v != -1) {
         s[v] = 1;
         p = Head[v].head1;
         while(p != NULL) {
            if( !s[p->VerAdj] && (dist[v] + p->weight < dist[p->VerAdj] || dist[p->VerAdj] == -1)) {
               dist[p->VerAdj] = dist[v] + p->weight;
               path[p->VerAdj] = v;
            }
            p = p->next;
         }
      }
   }
   int result[num_v];
   for(int i = 0; i < num_v; ++ i) {
      if(dist[i] == -1) {
         cout<<"从点"<<u<<"到点"<<i<<"不存在路径"<<endl;
      } else {
         cout<<"从点"<<u<<"到点"<<i<<"的加权路径长度为:"<<dist[i]<<endl;
         int cnt = 0;
         int a = i;
         result[cnt ++ ] = i;
         while(path[a] != -1) {
            result[cnt++] = path[a];
            a = path[a];
         }
         cout<<"最短路径为";
         for(int j = cnt - 1; j >= 0; -- j) {
            if(j != cnt - 1) {
               cout<<"->"<<result[j];
            } else {
               cout<<result[j];
            }
         }
         cout<<endl;
      }
   }
}

void Graph_Link::AllLength() {
   int edge[num_v][num_v];
   int floyd[num_v][num_v];
   for(int i = 0; i < num_v; ++ i) {
      for(int j = 0; j < num_v; ++ j) {
         if(i == j) {
            edge[i][j] = 0;
         } else {
            edge[i][j] = MAX_W;
         }
      }
   }
   Edge *p = NULL;
   for(int i = 0; i < num_v; ++ i) {
      p = Head[i].head1;
      while(p != NULL) {
         edge[i][p->VerAdj] = p->weight;
         p = p->next;
      }
   }
   int path[num_v][num_v];
   for(int i = 0; i < num_v; ++ i) {
      for(int j = 0; j < num_v; ++ j) {
         floyd[i][j] = edge[i][j];
         if(i != j && floyd[i][j] < MAX_W) {
            path[i][j] = i;
         } else {
            path[i][j] = -1;
         }
      }
   }
   for(int k = 0; k < num_v; ++ k) {
      for(int i = 0; i < num_v; ++ i) {
         if(i != k) {
            for(int j = 0; j < num_v; ++ j) {
               if(j != k && j != i && floyd[i][k] < MAX_W && floyd[k][j] < MAX_W) {
                  if(floyd[i][k] + floyd[k][j] < floyd[i][j]) {
                     floyd[i][j] = floyd[i][k] + floyd[k][j];
                     path[i][j] = path[k][j];
                  }
               }
            }
         }
      }
   }
   for(int i = 0; i < num_v; ++ i)  {
      for(int j = 0; j < num_v; ++ j) {
         if(i == j) {
            continue;
         }
         if(floyd[i][j] < MAX_W ) {
            cout<<"从点"<<i<<"到点"<<j<<"加权最短路径长度为:"<<floyd[i][j]<<endl;
            cout<<"最短路径为:";
            int result[num_v];
            memset(result, 0, sizeof(result));
            int cnt = 0;
            result[cnt] = j;
            while(path[i][result[cnt]] != i) {
               cnt ++ ;
               result[cnt] = path[i][result[cnt - 1]];
            }
            cnt ++ ;
            result[cnt] = i;
            for(int k = cnt; k > 0; -- k) {
               cout<<result[k]<<"->";
            }
            cout<<result[0]<<endl;
         } else {
            cout<<"从点"<<i<<"到点"<<j<<"不存在路径"<<endl;
         }
      }
   }
}

void Graph_Link::Prim(int u0) {
   int sumweight = 0;
   int lowcost[num_v];
   int nearvex[num_v];
   Edge *p = Head[u0].head1;
   for(int i = 0; i < num_v; ++ i) {
      lowcost[i] = MAX_W;
      nearvex[i] = u0;
   }
   while(p != NULL) {
      lowcost[p->VerAdj] = p->weight;
      p = p->next;
   }
   nearvex[u0] = -1;
   for(int i = 0; i < num_v; ++ i) {
      int min = MAX_W;
      int v = -1;
      for(int j = 0; j < num_v; ++ j) {
         if(nearvex[j] != -1 && lowcost[j] < min) {
            min = lowcost[j];
            v = j;
         }
      }
      if(v != -1) {
         printf("%d -> %d 这条边被选中,其权值是 %d\n", nearvex[v], v, lowcost[v]);
         nearvex[v] = -1;
         sumweight += lowcost[v];
         p = Head[v].head1;
         while(p != NULL) {
            if(nearvex[p->VerAdj] != -1 && p->weight < lowcost[p->VerAdj]) {
               lowcost[p->VerAdj] = p->weight;
               nearvex[p->VerAdj] = v;
            }
            p = p->next;
         }
      }
   }
   printf("最小生成树的总权值为:%d\n", sumweight);
}

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<stack>
#include<cstring>
#include<string>
#include"Graph.h"
#include<queue>

using namespace std;

int main()
{
   printf("请选择图的存储方式  0。邻接矩阵存储  1 邻接链表存储\n");
   int store;
   Graph *graph;
   scanf("%d", &store);
   FILE *fp = fopen("graph.txt", "r");
   if(store == 0) {
      graph = new Graph_Matrix(fp);
   } else {
      graph = new Graph_Link(fp);
   }
   fclose(fp);
   printf("请选择你要执行的操作\n0.退出\n1.向图中加入一条边\n2.从图中删除一条边\n3.图的深度优先遍历(递归)\n4.图的深度优先遍历(迭代)\n");
   printf("5.图的宽度优先遍历\n6.图的拓扑排序\n7.输出图的关键路径\n8.求无权图中顶点v到其他顶点的最短路径\n");
   printf("9.求正权图中顶点v到其他顶点的最短路径\n10.求正权图中每对顶点间的最短路径\n11.构造图的最小支撑树的普里姆算法\n");
   int choose;
   scanf("%d", &choose);
   int u, v, w;
   while(choose) {
      switch(choose) {
      case 1:
         printf("请输入所要插入边的两个顶点以及边的权值\n");
         scanf("%d %d %d", &u, &v, &w);
         graph->InsertEdge(u, v, w);
         break;
      case 2:
         printf("请输入所要删除边的两个顶点\n");
         scanf("%d %d", &u, &v);
         graph->DeleteEdge(u, v);
         break;
      case 3:
         graph->DepthFirstSearch();
         break;
      case 4:
         printf("请输入深度优先遍历(迭代)的起点");
         scanf("%d", &u);
         graph->DFS(u);
         break;
      case 5:
         printf("请输入宽度优先遍历的起点");
         scanf("%d", &u);
         graph->BFS(u);
         break;
      case 6:
         graph->TopoOrder();
         break;
      case 7:
         graph->CriticalPath();
         break;
      case 8:
         printf("请输入顶点v");
         scanf("%d", &v);
         graph->ShortestPath(v);
         break;
      case 9:
         printf("请输入顶点v");
         scanf("%d", &v);
         graph->DShortestPath(v);
         break;
      case 10:
         graph->AllLength();
         break;
      case 11:
         printf("请输入prim创建最小支撑树的起点");
         scanf("%d", &u);
         graph->Prim(u);
      }
      printf("请选择你要执行的操作\n0.退出\n1.向图中加入一条边\n2.从图中删除一条边\n3.图的深度优先遍历(递归)\n4.图的深度优先遍历(迭代)\n");
      printf("5.图的宽度优先遍历\n6.图的拓扑排序\n7.输出图的关键路径\n8.求无权图中顶点v到其他顶点的最短路径\n");
      printf("9.求正权图中顶点v到其他顶点的最短路径\n10.求正权图中每对顶点间的最短路径\n11.构造图的最小支撑树的普里姆算法\n");
      scanf("%d", &choose);
   }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值