#include <iostream>
#include <stdio.h>
#include <malloc.h>
#include <fstream>
#include <cstdlib>
#include <queue>
#include <string.h>
using namespace std;
#define MAX_VERTEX_NUM 20
#define N 100
bool visit[N]; //访问标记数组是全局变量
int dfn[N]; //顶点的先深编号
int count = 1;
int FLAG = 99999;
int in_order[N];
//无向图
struct MTGragh
{
int vertex [N]; //顶点表
int edge[N][N];//邻接矩阵—边表, 可视为边之间的关系
int n, e; //图的顶点数与边数
};
//正向链接表
typedef struct node //边表结点
{
int adjvex; //邻接点域(下标)
int cost; //边上的权值
struct node *next; //下一边链接指针
} EdgeNode;
typedef struct //顶点表结点
{
int vertex; //顶点数据域
EdgeNode * firstedge;//边链表头指针
} VertexNode;
typedef struct //图的邻接表
{
VertexNode vexlist [N];
int n,e; //顶点个数与边数
} AdjGraph;
//十字链表
typedef struct ArcBox
{
int tailvex, headvex; //该弧的尾和头顶点的位置
int cost; //该弧的信息
struct ArcBox * hlink, * tlink; //分别为弧头相同和弧尾相同的弧的链域
} ArcBox;
typedef struct VexNode
{
int data; //顶点值
ArcBox * firstin, * firstout; //分别指向该顶点第一条入弧和出弧
} VexNode;
typedef struct
{
VexNode xlist[MAX_VERTEX_NUM]; //表头向量
int n, e; //有向图的当前顶点数和弧数
} OLGraph;
//无向图的邻接多重表
typedef enum {unvisited, visited} VisitIf;
typedef struct EBox
{
VisitIf mark; //访问标记
int ivex, jvex; //该边依附的两个顶点的位置
struct EBox * ilink, * jlink; //分别指向依附这两个顶点的下一条边
int cost; //该边信息
} EBox;
typedef struct VexBox
{
int data;
EBox * firstedge; //分别指向该顶点第一条入弧和出弧
} VexBox;
struct AMLGraph
{
VexBox adjmulist[MAX_VERTEX_NUM];
int n,e; //无向图的当前顶点数和边数
};
void DFS(OLGraph *G, int v);
void Rev_DFS(OLGraph *G, int v);
//建立图的邻接矩阵
int CreateMGragh(MTGragh *G,int c[N],int flag,int sum)
{
int i, j;
G->n=c[1];
for (i=0; i<G->n; i++) //2.读入顶点信息,建立顶点表
G->vertex[i]=i;
for (i=0; i<G->n; i++)
for (j=0; j<G->n; j++)
G->edge[i][j]=0; //3.邻接矩阵初始化
int a,b;
int temp=0;
i=2;
if(flag==0)
{
while(i<sum)
{
a=c[i];
i++;
b=c[i];
i++;
G->edge[a][b] = c[i];
G->edge[b][a] = c[i];
temp++;
i++;
}
}
else
{
while(i<sum)
{
a=c[i];
i++;
b=c[i];
i++;
G->edge[a][b] = c[i];
//G->edge[b][a] = c[i];
temp++;
i++;
}
}
G->e=temp;
return G->e;
}
//输出无向图的邻接矩阵
void putMgraph(MTGragh G)
{
cout<<"无向图的邻接矩阵:"<<endl;
for(int i=0; i<G.n; i++)
{
cout<<i<<": ";
for(int j=0; j<G.n; j++)
{
cout<<G.edge[i][j]<<" ";
}
cout<<endl;
}
}
//建立图的链接表
AdjGraph CreateGraph(AdjGraph G,int c[N],int k)
{
G.n=c[1]; G.e=k;int j=2;
for(int i = 0; i < G.n; i++) //2.建立顶点表
{
G.vexlist[i].vertex=i; //2.1输入顶点信息
G.vexlist[i].firstedge = NULL;//2.2边表置为空表
}
for ( int i = 0; i < k; i++)//逐条边建立边表
{
int tail = c[j];
j++;
int head=c[j];
j++;
int weight = c[j];
j++;
EdgeNode * p = new EdgeNode; //建立边结点
p->adjvex = head;
p->cost = weight; //设置边结点
p->next = G.vexlist[tail].firstedge; //链入第 tail 号链表的前端
G.vexlist[tail].firstedge = p;
}
return G;
}
//输出有向图的链接表
void putGraph(AdjGraph A)
{
cout<<"有向图的链接表:"<<endl;
for(int i=0; i<A.n; i++)
{
cout<<A.vexlist[i].vertex<<" ";
if(A.vexlist[i].firstedge!=NULL)
{
EdgeNode *temp=A.vexlist[i].firstedge;
for(; temp!=NULL; temp=temp->next)
{
cout<<temp->adjvex<<","<<temp->cost<<" ";
}
}
cout<<endl;
}
}
//采用十字链表存储表示,构造有向图
void CreateDG(OLGraph &G,int c[N],int k)
{
G.n=c[1];
G.e=k;
for (int i = 0; i < G.n; i++)
{
//构造表头向量
G.xlist[i].data=i; //输入顶点值
G.xlist[i].firstin = NULL;
G.xlist[i].firstout = NULL; //初始化指针
}
int j=2;
for (int k = 0; k < G.e; k++)
{
//输入各弧并构造十字链表
int v1=c[j];//输入一条弧的始点和终点
j++;
int v2=c[j];
j++;
int weight=c[j];
j++;
ArcBox *p = new ArcBox;//假定有足够空间
//正向表
p->headvex=v2;
p->cost=weight;
p->hlink=G.xlist[v1].firstin;
G.xlist[v1].firstin=p;
//逆向表
p = new ArcBox;
p->tailvex=v1;
p->cost=weight;
p->tlink=G.xlist[v2].firstout;
G.xlist[v2].firstout=p;
}
}
//输出有向图的十字链表
void putDG(OLGraph G)
{
cout<<"有向图的十字链表:"<<endl;
for(int i=0; i<G.n; i++)
{
cout<<G.xlist[i].data<<" ";
cout<<"正向"<<" ";
if(G.xlist[i].firstin!=NULL)
{
ArcBox *temp = G.xlist[i].firstin;
for(; temp!=NULL; temp=temp->hlink)
cout<<temp->headvex<<","<<temp->cost<<" ";
}
cout<<"逆向"<<" ";
if(G.xlist[i].firstout!=NULL)
{
ArcBox *temp1 = G.xlist[i].firstout;
for(; temp1!=NULL; temp1=temp1->tlink)
cout<<temp1->tailvex<<","<<temp1->cost<<" ";
}
cout<<endl;
}
}
//用邻接多重表存储,构造无向图G
AMLGraph CreateUDG_AML(AMLGraph &G,int c[N],int k)
{
G.n=c[1];
G.e=k;
//cout<<G.e<<endl;
for(int i=0; i<G.n; i++)
{
G.adjmulist[i].data=i;
G.adjmulist[i].firstedge=NULL;
}
int sm=2;
for(int j=0; j<G.e; j++)
{
int v1=c[sm];
sm++;
int v2=c[sm];
sm++;
int weight=c[sm];
sm++;
EBox *p=new EBox;
p->ivex=v1;
p->jvex=v2;
p->cost=weight;
p->ilink=G.adjmulist[v1].firstedge;
p->jlink=G.adjmulist[v2].firstedge;
G.adjmulist[v1].firstedge=p;
G.adjmulist[v2].firstedge=p;
}
return G;
}
//输出无向图的多重链接表
void putAML(AMLGraph G)
{
cout<<"无向图的多重链接表"<<endl;
for(int i=0; i<G.n; i++)
{
cout<<G.adjmulist[i].data<<" ";
EBox *temp=G.adjmulist[i].firstedge;
if(G.adjmulist[i].firstedge!=NULL)
{
while(temp!=NULL)
{
if(temp->ivex==i)
{
cout<<temp->ivex<<" "<<temp->jvex<<" "<<temp->cost<<" ";
temp=temp->ilink;
}
else
{
cout<<temp->ivex<<" "<<temp->jvex<<" "<<temp->cost<<" ";
temp=temp->jlink;
}
}
}
cout<<endl;
}
}
//深度优先遍历
void DFS1(AdjGraph *G, int i) //以vi为出发点时对邻接表表示的图G进行先深搜索
{
EdgeNode *p;
cout<<G->vexlist[i].vertex<<" "; //访问顶点vi;
visit[i]=true; //标记vi已访问
//dfn[i]=count++; //对vi进行编号
p=G->vexlist[i].firstedge; //取vi边表的头指针
while(p)
{
//依次搜索vi的邻接点vj, 这里j=p->adjvex
if(!visit[p->adjvex]) //若vj尚未访问
DFS1(G,p->adjvex); //则以vj为出发点先深搜索
p=p->next;
}
}
//广度优先遍历
void BFS2(MTGragh *G, int k)
{
int j;
queue <int> Q;
cout << G->vertex[k]<<" "; //访问vk
visit[k] = true; //给vk作访问过标记
Q.push(k); //vk进队列
while (!Q.empty())
{
Q.pop();
j=0;
if (!visit[j])
{
cout<<G->vertex[j]<<" ";
visit[j]=true; //给vj作访问过标记
Q.push(j); //访问过的vj入队
}
j++;
}
}
//最小生成树普里姆(Prim)算法
void prim(MTGragh G)//begin作为初始顶点,n总的顶点数目
{
cout<<"最小生成树为:"<<endl;
int graph[N][N];
for(int i=0; i<G.n; i++)
{
for(int j=0; j<G.n; j++)
{
graph[i][j]=FLAG;
if(G.edge[i][j]!=0)
{
graph[i][j]=G.edge[i][j];
graph[j][i]=G.edge[i][j];
}
}
}
int begin=0;
int lowcost[N];
int mst[N];
for (int i = 0; i < G.n; i++) //初始化
{
if (i == begin)
continue;
lowcost[i] = graph[begin][i];//顶点1到其他定点的代价
mst[i] = begin;//初始都指向顶点begin
}
mst[begin] = 0;//顶点begin在MST集合里
lowcost[begin] = 0;
for (int i = 0; i < G.n; i++)
{
if (i == begin)
continue;
int min = FLAG;
int minid = 0;
for (int j = 0; j < G.n; j++) //寻找lowcost中最小的边
{
if (j == begin)
continue;
if (lowcost[j] < min&&lowcost[j] != 0)
{
min = lowcost[j];
minid = j;
}
}
lowcost[minid] = 0;
cout <<mst[minid] <<","<<minid <<" "<< min << endl;//输出找到的最小一条边
for (int j = 0; j < G.n; j++) //更新其他定点(主要变化的就是以minid为起始的边)
{
if (j == begin)
continue;
if (graph[minid][j] < lowcost[j])
{
lowcost[j] = graph[minid][j];
mst[j] = minid;
}
}
}
}
// Dijkstra 算法单源最短路径
void Dijkstra(MTGragh G)
{
cout<<"Dijkstra 算法最短路径为:"<<endl;
int D[G.n];
int Path[G.n];
bool S[G.n];
int source=0;
S[source] = true;
int graph[G.n][G.n];
for(int i=0; i<G.n; i++)
{
for(int j=0; j<G.n; j++)
{
graph[i][j]=FLAG;
if(G.edge[i][j]!=0)
{
graph[i][j]=G.edge[i][j];
}
if(i==j)
graph[i][j]=0;
}
}
for (int i = 0; i < G.n; i++)
{
D[i] = graph[source][i];
Path[i] = source;
}
int min_cost; // 权值最小
int min_cost_index; // 权值最小的下标
for (int i = 1; i < G.n; i++)
{
min_cost = FLAG;
for (int j = 0; j < G.n; j++)
{
if (S[j] == false && D[j] < min_cost) // 找到权值最小
{
min_cost = D[j];
min_cost_index = j;
}
}
D[min_cost_index] = true; // 该点已找到,进行标记
for (int j = 0; j < G.n; j++) // 更新 dist 数组
{// 确保两点之间有边
if (S[j]==false&&graph[min_cost_index][j]!=INT_MAX&&graph[min_cost_index][j]+min_cost<D[j])
{
D[j] = graph[min_cost_index][j] + min_cost;
Path[j] = min_cost_index;
}
}
}
for (int i = 0; i < G.n; i++)
{
if (i != source)
{
cout << source << "到" << i << "最短距离是:" << D[i] << ",路径是:" << i;
int t = Path[i];
while (t != source)
{
cout << "--" << t;
t = Path[t];
}
cout << "--" << source << endl;
}
}
}
//有向图强连通分支的Korasaju算法
void Korasaju(OLGraph *G)
{
cout<<"有向图强连通分支为:"<<endl;
int k=1, v, j ;
for (v=0; v<G->n; v++)
visit[v]=false ;
for (v=0; v<G->n; v++) //对图G正向遍历
if (!visit[v])
DFS(G,v) ;
for (v=0; v<G->n; v++)
visit[v]=false;
for (j=G->n-1; j>=0; j--)
{
v=in_order[j] ;
if (!visit[v])
{
cout<<k++<<" ";
Rev_DFS(G, v); //对图G逆向遍历
cout<<endl;
}
}
}
//拓扑排序算法
void Topologicalsort(AdjGraph G)
{
cout<<"拓扑排序算法为:"<<endl;
int i,j,k,top,m=0;
EdgeNode *p;
int d[G.n];
for(i=0; i<G.n; i++)
d[i]=0;
for(i=0; i<G.n; i++)
{
p=G.vexlist[i].firstedge;
while(p!=NULL)
{
j=p->adjvex;
d[j]++;
p=p->next;
}
}
top=-1;
for(i=0; i<G.n; i++)
{
if(d[i]==0)
{
d[i]=top;
top=i;
}
}
while(top!=-1)
{
j=top;
top=d[top];
cout<<j<<" ";
m++;
p=G.vexlist[j].firstedge;
while(p!=NULL)
{
k=p->adjvex;
d[k]--;
if(d[k]==0)
{
d[k]=top;
top=k;
}
p=p->next;
}
}
if(m<G.n)
cout<<"有回路"<<endl;
}
int main()
{
ifstream infile;
int data[N];
infile.open("data.txt");
int value;
infile >> value;
int sum=0;
int i=0;
while(infile.good())
{
sum++;
data[i]=value;
i++;
infile >> value;
}
cout<<"所有的数据为:"<<endl;
for(int i=0; i<sum; i++)
cout<<data[i]<<" ";
cout<<endl;
cout<<endl;
MTGragh G;
int flag=data[0];
int k=CreateMGragh(&G,data,flag,sum);
putMgraph(G);
cout<<endl;
AdjGraph A;
putGraph(CreateGraph(A,data,k));
cout<<endl;
OLGraph K;
CreateDG(K,data,k);
putDG(K);
cout<<endl;
AMLGraph AC=CreateUDG_AML(AC,data,k);
putAML(AC);
cout<<endl;
// 先深搜索一邻接表表示的图G
cout<<"深度优先遍历(DFS)结果为:"<<endl;
AdjGraph SK = CreateGraph(SK,data,k);
for ( int i = 0; i < SK.n; i++ )
visit[i] =false; //标志数组初始化
for ( int i = 0; i < SK.n; i++ )
if (!visit[i])
DFS1(&SK,i); //从顶点 i 出发的一次搜索
cout<<endl;
cout<<endl;
flag =1;
MTGragh SB;
CreateMGragh(&SB,data,flag,sum);
cout<<"广度优先遍历(BFS)结果为:"<<endl;
for(int i = 0; i < SB.n; i++ )
visit[i]=false; //标志数组初始化
for(int i = 0; i < SB.n; i++ )
if (!visit[i])
BFS2(&SB,i); //从顶点 i 出发的一次搜索
cout<<endl;
cout<<endl;
prim(G);
cout<<endl;
Dijkstra(G);
cout<<endl;
Korasaju(&K);
cout<<endl;
AdjGraph MM=CreateGraph(MM,data,k);
Topologicalsort(MM);
return 0;
}
void DFS(OLGraph *G, int v)
{
ArcBox *p;
visit[v]=true ;
for(p=G->xlist[v].firstout ; p!=NULL ; p=p->tlink)
if(!visit[p->tailvex])
DFS(G,p->tailvex);
in_order[count++]=v;
}
void Rev_DFS(OLGraph *G, int v)
{
ArcBox *p ;
visit[v]=true;
cout<<v<<" ";
for(p=G->xlist[v].firstin ; p!=NULL ; p=p->hlink)
if(!visit[p->headvex])
Rev_DFS(G,p->headvex);
//cout<<endl;
}
#include <stdio.h>
#include <malloc.h>
#include <fstream>
#include <cstdlib>
#include <queue>
#include <string.h>
using namespace std;
#define MAX_VERTEX_NUM 20
#define N 100
bool visit[N]; //访问标记数组是全局变量
int dfn[N]; //顶点的先深编号
int count = 1;
int FLAG = 99999;
int in_order[N];
//无向图
struct MTGragh
{
int vertex [N]; //顶点表
int edge[N][N];//邻接矩阵—边表, 可视为边之间的关系
int n, e; //图的顶点数与边数
};
//正向链接表
typedef struct node //边表结点
{
int adjvex; //邻接点域(下标)
int cost; //边上的权值
struct node *next; //下一边链接指针
} EdgeNode;
typedef struct //顶点表结点
{
int vertex; //顶点数据域
EdgeNode * firstedge;//边链表头指针
} VertexNode;
typedef struct //图的邻接表
{
VertexNode vexlist [N];
int n,e; //顶点个数与边数
} AdjGraph;
//十字链表
typedef struct ArcBox
{
int tailvex, headvex; //该弧的尾和头顶点的位置
int cost; //该弧的信息
struct ArcBox * hlink, * tlink; //分别为弧头相同和弧尾相同的弧的链域
} ArcBox;
typedef struct VexNode
{
int data; //顶点值
ArcBox * firstin, * firstout; //分别指向该顶点第一条入弧和出弧
} VexNode;
typedef struct
{
VexNode xlist[MAX_VERTEX_NUM]; //表头向量
int n, e; //有向图的当前顶点数和弧数
} OLGraph;
//无向图的邻接多重表
typedef enum {unvisited, visited} VisitIf;
typedef struct EBox
{
VisitIf mark; //访问标记
int ivex, jvex; //该边依附的两个顶点的位置
struct EBox * ilink, * jlink; //分别指向依附这两个顶点的下一条边
int cost; //该边信息
} EBox;
typedef struct VexBox
{
int data;
EBox * firstedge; //分别指向该顶点第一条入弧和出弧
} VexBox;
struct AMLGraph
{
VexBox adjmulist[MAX_VERTEX_NUM];
int n,e; //无向图的当前顶点数和边数
};
void DFS(OLGraph *G, int v);
void Rev_DFS(OLGraph *G, int v);
//建立图的邻接矩阵
int CreateMGragh(MTGragh *G,int c[N],int flag,int sum)
{
int i, j;
G->n=c[1];
for (i=0; i<G->n; i++) //2.读入顶点信息,建立顶点表
G->vertex[i]=i;
for (i=0; i<G->n; i++)
for (j=0; j<G->n; j++)
G->edge[i][j]=0; //3.邻接矩阵初始化
int a,b;
int temp=0;
i=2;
if(flag==0)
{
while(i<sum)
{
a=c[i];
i++;
b=c[i];
i++;
G->edge[a][b] = c[i];
G->edge[b][a] = c[i];
temp++;
i++;
}
}
else
{
while(i<sum)
{
a=c[i];
i++;
b=c[i];
i++;
G->edge[a][b] = c[i];
//G->edge[b][a] = c[i];
temp++;
i++;
}
}
G->e=temp;
return G->e;
}
//输出无向图的邻接矩阵
void putMgraph(MTGragh G)
{
cout<<"无向图的邻接矩阵:"<<endl;
for(int i=0; i<G.n; i++)
{
cout<<i<<": ";
for(int j=0; j<G.n; j++)
{
cout<<G.edge[i][j]<<" ";
}
cout<<endl;
}
}
//建立图的链接表
AdjGraph CreateGraph(AdjGraph G,int c[N],int k)
{
G.n=c[1]; G.e=k;int j=2;
for(int i = 0; i < G.n; i++) //2.建立顶点表
{
G.vexlist[i].vertex=i; //2.1输入顶点信息
G.vexlist[i].firstedge = NULL;//2.2边表置为空表
}
for ( int i = 0; i < k; i++)//逐条边建立边表
{
int tail = c[j];
j++;
int head=c[j];
j++;
int weight = c[j];
j++;
EdgeNode * p = new EdgeNode; //建立边结点
p->adjvex = head;
p->cost = weight; //设置边结点
p->next = G.vexlist[tail].firstedge; //链入第 tail 号链表的前端
G.vexlist[tail].firstedge = p;
}
return G;
}
//输出有向图的链接表
void putGraph(AdjGraph A)
{
cout<<"有向图的链接表:"<<endl;
for(int i=0; i<A.n; i++)
{
cout<<A.vexlist[i].vertex<<" ";
if(A.vexlist[i].firstedge!=NULL)
{
EdgeNode *temp=A.vexlist[i].firstedge;
for(; temp!=NULL; temp=temp->next)
{
cout<<temp->adjvex<<","<<temp->cost<<" ";
}
}
cout<<endl;
}
}
//采用十字链表存储表示,构造有向图
void CreateDG(OLGraph &G,int c[N],int k)
{
G.n=c[1];
G.e=k;
for (int i = 0; i < G.n; i++)
{
//构造表头向量
G.xlist[i].data=i; //输入顶点值
G.xlist[i].firstin = NULL;
G.xlist[i].firstout = NULL; //初始化指针
}
int j=2;
for (int k = 0; k < G.e; k++)
{
//输入各弧并构造十字链表
int v1=c[j];//输入一条弧的始点和终点
j++;
int v2=c[j];
j++;
int weight=c[j];
j++;
ArcBox *p = new ArcBox;//假定有足够空间
//正向表
p->headvex=v2;
p->cost=weight;
p->hlink=G.xlist[v1].firstin;
G.xlist[v1].firstin=p;
//逆向表
p = new ArcBox;
p->tailvex=v1;
p->cost=weight;
p->tlink=G.xlist[v2].firstout;
G.xlist[v2].firstout=p;
}
}
//输出有向图的十字链表
void putDG(OLGraph G)
{
cout<<"有向图的十字链表:"<<endl;
for(int i=0; i<G.n; i++)
{
cout<<G.xlist[i].data<<" ";
cout<<"正向"<<" ";
if(G.xlist[i].firstin!=NULL)
{
ArcBox *temp = G.xlist[i].firstin;
for(; temp!=NULL; temp=temp->hlink)
cout<<temp->headvex<<","<<temp->cost<<" ";
}
cout<<"逆向"<<" ";
if(G.xlist[i].firstout!=NULL)
{
ArcBox *temp1 = G.xlist[i].firstout;
for(; temp1!=NULL; temp1=temp1->tlink)
cout<<temp1->tailvex<<","<<temp1->cost<<" ";
}
cout<<endl;
}
}
//用邻接多重表存储,构造无向图G
AMLGraph CreateUDG_AML(AMLGraph &G,int c[N],int k)
{
G.n=c[1];
G.e=k;
//cout<<G.e<<endl;
for(int i=0; i<G.n; i++)
{
G.adjmulist[i].data=i;
G.adjmulist[i].firstedge=NULL;
}
int sm=2;
for(int j=0; j<G.e; j++)
{
int v1=c[sm];
sm++;
int v2=c[sm];
sm++;
int weight=c[sm];
sm++;
EBox *p=new EBox;
p->ivex=v1;
p->jvex=v2;
p->cost=weight;
p->ilink=G.adjmulist[v1].firstedge;
p->jlink=G.adjmulist[v2].firstedge;
G.adjmulist[v1].firstedge=p;
G.adjmulist[v2].firstedge=p;
}
return G;
}
//输出无向图的多重链接表
void putAML(AMLGraph G)
{
cout<<"无向图的多重链接表"<<endl;
for(int i=0; i<G.n; i++)
{
cout<<G.adjmulist[i].data<<" ";
EBox *temp=G.adjmulist[i].firstedge;
if(G.adjmulist[i].firstedge!=NULL)
{
while(temp!=NULL)
{
if(temp->ivex==i)
{
cout<<temp->ivex<<" "<<temp->jvex<<" "<<temp->cost<<" ";
temp=temp->ilink;
}
else
{
cout<<temp->ivex<<" "<<temp->jvex<<" "<<temp->cost<<" ";
temp=temp->jlink;
}
}
}
cout<<endl;
}
}
//深度优先遍历
void DFS1(AdjGraph *G, int i) //以vi为出发点时对邻接表表示的图G进行先深搜索
{
EdgeNode *p;
cout<<G->vexlist[i].vertex<<" "; //访问顶点vi;
visit[i]=true; //标记vi已访问
//dfn[i]=count++; //对vi进行编号
p=G->vexlist[i].firstedge; //取vi边表的头指针
while(p)
{
//依次搜索vi的邻接点vj, 这里j=p->adjvex
if(!visit[p->adjvex]) //若vj尚未访问
DFS1(G,p->adjvex); //则以vj为出发点先深搜索
p=p->next;
}
}
//广度优先遍历
void BFS2(MTGragh *G, int k)
{
int j;
queue <int> Q;
cout << G->vertex[k]<<" "; //访问vk
visit[k] = true; //给vk作访问过标记
Q.push(k); //vk进队列
while (!Q.empty())
{
Q.pop();
j=0;
if (!visit[j])
{
cout<<G->vertex[j]<<" ";
visit[j]=true; //给vj作访问过标记
Q.push(j); //访问过的vj入队
}
j++;
}
}
//最小生成树普里姆(Prim)算法
void prim(MTGragh G)//begin作为初始顶点,n总的顶点数目
{
cout<<"最小生成树为:"<<endl;
int graph[N][N];
for(int i=0; i<G.n; i++)
{
for(int j=0; j<G.n; j++)
{
graph[i][j]=FLAG;
if(G.edge[i][j]!=0)
{
graph[i][j]=G.edge[i][j];
graph[j][i]=G.edge[i][j];
}
}
}
int begin=0;
int lowcost[N];
int mst[N];
for (int i = 0; i < G.n; i++) //初始化
{
if (i == begin)
continue;
lowcost[i] = graph[begin][i];//顶点1到其他定点的代价
mst[i] = begin;//初始都指向顶点begin
}
mst[begin] = 0;//顶点begin在MST集合里
lowcost[begin] = 0;
for (int i = 0; i < G.n; i++)
{
if (i == begin)
continue;
int min = FLAG;
int minid = 0;
for (int j = 0; j < G.n; j++) //寻找lowcost中最小的边
{
if (j == begin)
continue;
if (lowcost[j] < min&&lowcost[j] != 0)
{
min = lowcost[j];
minid = j;
}
}
lowcost[minid] = 0;
cout <<mst[minid] <<","<<minid <<" "<< min << endl;//输出找到的最小一条边
for (int j = 0; j < G.n; j++) //更新其他定点(主要变化的就是以minid为起始的边)
{
if (j == begin)
continue;
if (graph[minid][j] < lowcost[j])
{
lowcost[j] = graph[minid][j];
mst[j] = minid;
}
}
}
}
// Dijkstra 算法单源最短路径
void Dijkstra(MTGragh G)
{
cout<<"Dijkstra 算法最短路径为:"<<endl;
int D[G.n];
int Path[G.n];
bool S[G.n];
int source=0;
S[source] = true;
int graph[G.n][G.n];
for(int i=0; i<G.n; i++)
{
for(int j=0; j<G.n; j++)
{
graph[i][j]=FLAG;
if(G.edge[i][j]!=0)
{
graph[i][j]=G.edge[i][j];
}
if(i==j)
graph[i][j]=0;
}
}
for (int i = 0; i < G.n; i++)
{
D[i] = graph[source][i];
Path[i] = source;
}
int min_cost; // 权值最小
int min_cost_index; // 权值最小的下标
for (int i = 1; i < G.n; i++)
{
min_cost = FLAG;
for (int j = 0; j < G.n; j++)
{
if (S[j] == false && D[j] < min_cost) // 找到权值最小
{
min_cost = D[j];
min_cost_index = j;
}
}
D[min_cost_index] = true; // 该点已找到,进行标记
for (int j = 0; j < G.n; j++) // 更新 dist 数组
{// 确保两点之间有边
if (S[j]==false&&graph[min_cost_index][j]!=INT_MAX&&graph[min_cost_index][j]+min_cost<D[j])
{
D[j] = graph[min_cost_index][j] + min_cost;
Path[j] = min_cost_index;
}
}
}
for (int i = 0; i < G.n; i++)
{
if (i != source)
{
cout << source << "到" << i << "最短距离是:" << D[i] << ",路径是:" << i;
int t = Path[i];
while (t != source)
{
cout << "--" << t;
t = Path[t];
}
cout << "--" << source << endl;
}
}
}
//有向图强连通分支的Korasaju算法
void Korasaju(OLGraph *G)
{
cout<<"有向图强连通分支为:"<<endl;
int k=1, v, j ;
for (v=0; v<G->n; v++)
visit[v]=false ;
for (v=0; v<G->n; v++) //对图G正向遍历
if (!visit[v])
DFS(G,v) ;
for (v=0; v<G->n; v++)
visit[v]=false;
for (j=G->n-1; j>=0; j--)
{
v=in_order[j] ;
if (!visit[v])
{
cout<<k++<<" ";
Rev_DFS(G, v); //对图G逆向遍历
cout<<endl;
}
}
}
//拓扑排序算法
void Topologicalsort(AdjGraph G)
{
cout<<"拓扑排序算法为:"<<endl;
int i,j,k,top,m=0;
EdgeNode *p;
int d[G.n];
for(i=0; i<G.n; i++)
d[i]=0;
for(i=0; i<G.n; i++)
{
p=G.vexlist[i].firstedge;
while(p!=NULL)
{
j=p->adjvex;
d[j]++;
p=p->next;
}
}
top=-1;
for(i=0; i<G.n; i++)
{
if(d[i]==0)
{
d[i]=top;
top=i;
}
}
while(top!=-1)
{
j=top;
top=d[top];
cout<<j<<" ";
m++;
p=G.vexlist[j].firstedge;
while(p!=NULL)
{
k=p->adjvex;
d[k]--;
if(d[k]==0)
{
d[k]=top;
top=k;
}
p=p->next;
}
}
if(m<G.n)
cout<<"有回路"<<endl;
}
int main()
{
ifstream infile;
int data[N];
infile.open("data.txt");
int value;
infile >> value;
int sum=0;
int i=0;
while(infile.good())
{
sum++;
data[i]=value;
i++;
infile >> value;
}
cout<<"所有的数据为:"<<endl;
for(int i=0; i<sum; i++)
cout<<data[i]<<" ";
cout<<endl;
cout<<endl;
MTGragh G;
int flag=data[0];
int k=CreateMGragh(&G,data,flag,sum);
putMgraph(G);
cout<<endl;
AdjGraph A;
putGraph(CreateGraph(A,data,k));
cout<<endl;
OLGraph K;
CreateDG(K,data,k);
putDG(K);
cout<<endl;
AMLGraph AC=CreateUDG_AML(AC,data,k);
putAML(AC);
cout<<endl;
// 先深搜索一邻接表表示的图G
cout<<"深度优先遍历(DFS)结果为:"<<endl;
AdjGraph SK = CreateGraph(SK,data,k);
for ( int i = 0; i < SK.n; i++ )
visit[i] =false; //标志数组初始化
for ( int i = 0; i < SK.n; i++ )
if (!visit[i])
DFS1(&SK,i); //从顶点 i 出发的一次搜索
cout<<endl;
cout<<endl;
flag =1;
MTGragh SB;
CreateMGragh(&SB,data,flag,sum);
cout<<"广度优先遍历(BFS)结果为:"<<endl;
for(int i = 0; i < SB.n; i++ )
visit[i]=false; //标志数组初始化
for(int i = 0; i < SB.n; i++ )
if (!visit[i])
BFS2(&SB,i); //从顶点 i 出发的一次搜索
cout<<endl;
cout<<endl;
prim(G);
cout<<endl;
Dijkstra(G);
cout<<endl;
Korasaju(&K);
cout<<endl;
AdjGraph MM=CreateGraph(MM,data,k);
Topologicalsort(MM);
return 0;
}
void DFS(OLGraph *G, int v)
{
ArcBox *p;
visit[v]=true ;
for(p=G->xlist[v].firstout ; p!=NULL ; p=p->tlink)
if(!visit[p->tailvex])
DFS(G,p->tailvex);
in_order[count++]=v;
}
void Rev_DFS(OLGraph *G, int v)
{
ArcBox *p ;
visit[v]=true;
cout<<v<<" ";
for(p=G->xlist[v].firstin ; p!=NULL ; p=p->hlink)
if(!visit[p->headvex])
Rev_DFS(G,p->headvex);
//cout<<endl;
}