您的位置:首页 > 理论基础 > 数据结构算法

数据结构第五次作业(图的基本操作实现)

2016-10-31 21:46 399 查看
实验题目: 图的基本操作实现               

实验目的:掌握图的邻接矩阵和邻接表两个存储结构及表示。
          掌握图的DFS和BFS两种遍历算法。
          理解并掌握下述完整算法的基本思想以及算法实现方法:最小生成树算法、最短路径算法、拓扑排序算法及关键路径算法。
实验内容:1. 创建一个无向图,并分别对其进行DFS和BFS。
          2. 实现最短路径、最小生成树、拓扑排序三种算法。
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<stdlib.h>
#include<iostream>
#include<queue>
using namespace std;
const int INF=1e8-1;
int n,m;
bool vis[1010];
int dist[1010];
int indegree[1010];
bool mark[1010][1010];
int map[1010][1010];
int road[1010][1010];
/* 测试数据
1 2 6
1 3 11
1 4 5
2 3 4
2 4 7
3 4 9
*/
void dfs(int x) // 深搜
{
cout<<x;
vis[x]=1;
for(int i=2;i<=n;i++)
{
if(!vis[i]&&map[x][i]!=INF)
dfs(i);
}
}

void bfs(int x) // 广搜
{
cout<<x;
vis[x]=1;
queue<int> Q;
Q.push(x);
while(!Q.empty())
{
int t;
t=Q.front();
Q.pop();
for(int i=2;i<=n;i++)
{
if(!vis[i]&&map[x][i]!=INF)
{
cout<<i;
vis[i]=1;
Q.push(i);
}
}
}
}

int prim() // 普里姆算法求最小生成树
{
int ans=0;
for(int i=0;i<1010;i++)
dist[i]=INF;
dist[1]=0;
for(int i=1;i<=n;i++)
{
int k,tp=INF;
for(int j=1;j<=n;j++)
{
if(!vis[j]&&dist[j]<tp)
{
k=j;
tp=dist[j];
}
}
vis[k]=1;
ans+=tp;
for(int j=1;j<=n;j++)
{
if(!vis[j]&&map[k][j]<dist[j])
{
dist[j]=map[k][j];
}
}
}
return ans;
}

void floyd() // 佛洛伊德算法求最短路
{
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
road[i][j]=map[i][j];
for(int k=1;k<=n;k++)
{
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
road[i][j]=min(road[i][j],road[i][k]+road[k][j]);
}
}
}
}

void topo()
{
int tpsort[1010];
int x,num=0;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(indegree[j]==0)
{
x=j;
break;
}
}
tpsort[num++]=x;
indegree[x]=-1;
for(int j=1;j<=n;j++)
{
if(mark[x][j])
indegree[j]--;
}
}
for(int i=0;i<num;i++)
printf(i==num-1?"%d\n":"%d ",tpsort[i]);
}

int main()
{
printf("\n********************************\n\n");
puts("1. 建图");
puts("2. DFS遍历");
puts("3. BFS遍历");
puts("4. 连通该图所有顶点的最小代价");
puts("5. 两点之间的最短路径");
puts("6. 输出拓扑排序后的序列");
puts("0. 退出");
printf("\n********************************\n\n");
int choose;
while(scanf("%d",&choose),choose)
{
switch(choose)
{
case 1:
printf("请分别输入图的顶点总数和边的总数:");
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
map[i][j]=(i==j?0:INF);
}
}
printf("请输入边的两个端点及权值:\n");
memset(indegree,0,sizeof(indegree));
memset(mark,0,sizeof(mark));
for(int i=1;i<=m;i++)
{
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
if(map[u][v]>w)
map[u][v]=map[v][u]=w;
if(!mark[u][v])
{
mark[u][v]=1;
indegree[v]++;
}
}
puts("成功建图\n");
break;
case 2:
memset(vis,0,sizeof(vis));
dfs(1);
puts("\n");
break;
case 3:
memset(vis,0,sizeof(vis));
bfs(1);
puts("\n");
break;
case 4:
memset(vis,0,sizeof(vis));
printf("最小代价为:%d\n\n",prim());
break;
case 5:
floyd();
printf("请输入您想要查询的两个点:");
int a,b;
scanf("%d%d",&a,&b);
printf("两点之间的最短路径为:%d\n\n",road[a][b]);
break;
case 6:
topo();
puts("\n");
break;
}
}
system("pause");
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: