数据结构(C语言)-图子系统(实验)

一、实验目的

(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);
}

5、运行结果

在这里插入图片描述

  • 5
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值