一、实验目的
(1)掌握图邻接矩阵的存储方法。
(2)掌握图的深度优先遍历的基本思想。
(3)掌握图的广度优先遍历的基本思想。
(4)掌握普利姆算法与克鲁斯卡尔算法
(5)掌握利用迪杰斯特拉算法求最短路径
二、实验内容
(1)编写为从键盘输入的数据建立邻接矩阵存储
(2)编写图的深度优先遍历算法
(3)编写图的广度优先遍历算法
(4)编写普利姆算法与克鲁斯卡尔算法
(5)编写迪杰斯特拉算法求最短路径
三、实验步骤
(1)输入并调试程序
(2)建立无向网 并输出邻接矩阵
(3)对该图从某一顶点开始进行深度优先遍历
(4)对该图从某一顶点开始进行广度优先遍历
(5)用两种算法输出最小生成树
(6)对该图从某一顶点开始进行最短路径求解
四、参考程序
//本程序仅供参考
#define MAX 100
#define MAXS 1000//极大值
#include<stdio.h>
typedef struct {
int e,n; //顶点数,边数
char vexs[MAX];//顶点数组
int visited[MAX];//深度遍历辅助数组
int egrs[MAX][MAX];//邻接矩阵数组
}MGrage;
//克鲁斯卡尔算法要用的结构体
typedef struct {
char u;//记录边的起始点
char v;//记录边的终点
int w;//记录边的权值
}Edge;
Edge E[MAX];
void CreateMGrage(MGrage *h){
int i,j,k;
char ch1,ch2;
printf("请输入顶点数:");
scanf("%d",&h->e);
printf("请输入边数:");
scanf("%d",&h->n);
for(i=0;i<h->e;i++){
getchar();
printf("输入第%d个顶点:",i+1);
scanf("%c",&(h->vexs[i]));
}
for(i=0;i<h->e;i++){
for(j=0;j<h->e;j++){
h->egrs[i][j]=MAXS;
}
}
for(k=0;k<h->n;k++){
int x;
getchar();
printf("建立第%d条边(格式X,X,权值):",k+1);
scanf("%c,%c,%d",&ch1,&ch2,&x);
E[k].u=ch1;E[k].v=ch2;E[k].w=x;
for(i=0;i<h->e;i++){
for(j=0;j<h->e;j++){
if(ch1==h->vexs[i]&&ch2==h->vexs[j]) {
h->egrs[i][j]=x;
h->egrs[j][i]=x;
}
}
}
}
}
void ScMGrage(MGrage *h){
int i,j;
printf("网的邻接矩阵(无向):\n");
for(i=0;i<h->e;i++){
printf("%c",h->vexs[i]);
for(j=0;j<h->e;j++){
printf("%5d",h->egrs[i][j]);
}
printf("\n");
}
}
void visit(MGrage *h){//初始化辅助数组
int i;
for(i=0;i<h->e;i++){
h->visited[i]=0;
}
}
void DFS(MGrage *h,int x){//深度优先遍历
int i;
h->visited[x-1]=1;//访问第x个顶点
for(i=0;i<h->n;i++){
if((h->egrs[x-1][i]!=0)&&(h->visited[i]==0)){//依次检查邻接矩阵x所在的行
printf("%5c",h->vexs[i]);
DFS(h,i+1);//i是v的邻接点,如果i未访问,则递归调用DFS
}
}
}
void BFS(MGrage *h,int x){//广度优先遍历
int i,v,visited[MAX];
int qu[MAX],front =0,rear=0;
for(i=0;i<h->e;i++){
visited[i]=0;
}
visited[x]=1;
rear=(rear+1)%MAX;
qu[rear]=x;
while(front!=rear){
front=(front+1)%MAX;
v=qu[front];
for(i=0;i<h->n;i++){
for(v=0;v<h->e;v++){
if(visited[i]==0){
visited[i]=1;
printf("%5c",h->vexs[i]);
rear=(rear+1)%MAX;
qu[rear]=i;
}
}
}
}
}
//普里姆算法
void Prim(MGrage *h){
int i,j,k, min,lowcost[MAX],closest[MAX];
for(i=0;i<h->e;i++){//从邻接矩阵第零行开始
lowcost[i]=h->egrs[0][i];//将第0行的数组信息赋值到lowcost数组中
closest[i]=0;
}
closest[0]=-1;//设置初值-1
for(i=0;i<h->e;i++){//从U之外求离U中某一顶点最近的顶点
min=MAXS;k=i;
for(j=0;j<h->e;j++){//从邻接矩阵第1行开始找各权值中最小值
if(lowcost[j]<min&&closest[j]!=-1){
min=lowcost[j];//最小值设为当前边的权值
k=j;//此边依附顶点
}
}
if(closest[k]!=-1){
printf("(%c,%c) 权值%d\n",h->vexs[closest[k]],h->vexs[k],lowcost[k]);//打印生成树该边及其权值
}
closest[k]=-1;//K加入到U中
for(j=0;j<h->e;j++){//设顶点k为下次查找的起始点
if(closest[j]!=-1&&h->egrs[k][j]<lowcost[j]){
lowcost[j]=h->egrs[k][j];
closest[j]=k;
}
}
}
}
//克鲁斯卡尔算法
void sort(MGrage *h){
int i,j;
Edge t;
for(i=0;i<h->n-1;i++){//为边表进行从小到大排序算法
for(j=i+1;j<h->n;j++){
if(E[i].w>E[j].w){
t=E[i];
E[i]=E[j];
E[j]=t;
}
}
}
}
int seeks(int set[],int v){
int i=v;
while(set[i]>0){//查看顶点V在哪个连通集合
i=set[i];
}
return(i);
}
void Krusjal(MGrage *h,Edge E[]){//E所表示的图是按权值从小到大排序
int set[MAX];//辅助数组
int v1,v2,i;
for(i=0;i<MAX;i++){
set[i]=0;//给set中每一个元素赋
}
i=0;//i表示待获取的生成树中的 边数,初值为 1
while(i<h->n){
v1=seeks(set,E[i].u);//确定顶点V所在的连通集
v2=seeks(set,E[i].v);
if(v1!=v2){//当V1,V2不在同一顶点集合,确定该边应当选入生成树
printf("(%c,%c) 权值 %d\n",E[i].u,E[i].v,E[i].w);
set[v1]=v2;//将v2加入到v1的集合中
}
i++;
}
}
void Dijkstra(MGrage *h,int v){//迪杰斯特拉算法求最短路径
int dist[MAX],path[MAX],s[MAX];
int mindis,i,j,u,pre;
for(i=0;i<h->e;i++){
dist[i]=h->egrs[v][i];
s[i]=0;
if(h->egrs[v][i]<MAXS){
path[i]=v;
}else{
path[i]=-1;
}
}
s[v]=1;path[v]=0;
for(i=0;i<h->e;i++){
mindis=MAXS;
u=-1;
for(j=0;j<h->e;j++){
if(s[j]==0&&dist[j]<mindis){
u=j;
mindis=dist[j];
}
}
if(u!=-1){
s[u]=1;
for(j=0;j<h->e;j++){
if(s[j]==0){
if(h->egrs[u][j]<MAXS&&dist[u]+h->egrs[u][j]<dist[j]){
dist[j]=dist[u]+h->egrs[u][j];
path[j]=u;
}
}
}
}
}
printf("\nDijkstra算法求解如下:");
for(i=0;i<h->e;i++){
if(i!=v){
printf("\n%c->%c:",h->vexs[v],h->vexs[i]);
if(s[i]==1){
printf("路径长度为%2d,",dist[i]);
pre=i;
printf("路径逆序为:");
while(pre!=v){
printf("%c,",h->vexs[pre]);
pre=path[pre];
}
printf("%c",h->vexs[pre]);
}else{
printf("不存在路径\n");
}
}
}
}
int main(){
MGrage h;
int v,i,x;
char k;
CreateMGrage(&h);
ScMGrage(&h);
printf("从第几个顶点开始(1~%d):",h.e);
scanf("%d",&x);
printf("从%c深度遍历为:\n",h.vexs[x-1]);
DFS(&h,x);
printf("\n从%c广度遍历:\n",h.vexs[x-1]);
BFS(&h,x-1);
printf("\n普利姆算法:\n");
Prim(&h);
sort(&h);
printf("\n克鲁斯卡尔算法:\n");
Krusjal(&h, E);
printf("输入开始顶点(A~%c):",h.vexs[h.e-1]);
scanf("%c",&k);
scanf("%c",&k);
for(i=0;i<h.e;i++){
if(x==h.vexs[i]){
v=i;
}
}
Dijkstra(&h,v);
}