图类的实现
两种存储结构的邻接矩阵和邻接链表存储的都实现了,实现了图类的大部分算法
#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);
}
}