【数据结构】图-创建图、求顶点度、Dijkstra算法求最短路径

首先是邻接表的库 ljb.h

/*********************************************/
/*              邻接表存储结构          	 */
/*********************************************/

#include 
#include 
#define M 100		    	/*图的最大顶点数*/
typedef char VertexType;    /*顶点信息数据类型*/
typedef struct ArcNode{     /*边表结点*/
	int adjvex;
	int info;
	struct ArcNode *nextarc;
}ArcNode;

typedef struct Vnode{       /*头结点类型*/
	VertexType data;        /*顶点信息*/
	ArcNode *firstarc;      /*邻接链表头指针*/
}Vnode;

typedef struct{           /*邻接表类型*/
	Vnode Vertex[M];      /*存放头结点的顺序表*/
	int numV,numE;        /*图的顶点数与边数*/
}AdjList;

/* 函数功能:建立图的邻接表 */ 
void creat(AdjList *G,int n,int e)
{
	int i,vi,vj,w;
	ArcNode *q1,*q2;
	G->numV =n;
	G->numE =e;
	printf("输入顶点的信息:\n");
	for( i=0; i<G->numV; i++ )
	{
    	printf("%d:",i+1);   
    	scanf("%c",&G->Vertex[i].data );
		getchar();
		G->Vertex[i].firstarc=NULL;      
	}
 	for(i=0; i<G->numE; i++ )
	{
		printf("输入边的信息及权值(vi,vj,w):"); 
      	scanf("%d,%d,%d",&vi,&vj,&w);          /*无向图*/
      	q1=(ArcNode*)malloc(sizeof(ArcNode));
 		q1->adjvex=vj-1; q1->info=w; q1->nextarc=NULL;
 		q1->nextarc= G->Vertex[vi-1].firstarc; 
 		G->Vertex[vi-1].firstarc=q1; 
 		q2=(ArcNode*)malloc(sizeof(ArcNode));
 		q2->adjvex=vi-1; q2->info=w; q2->nextarc=NULL;
 		q2->nextarc= G->Vertex[vj-1].firstarc; 
 		G->Vertex[vj-1].firstarc=q2; 
	}
}

/* 函数功能:输出图的邻接表 */
void print(AdjList G)
{
	ArcNode *p;
	int i;
	for(i=0;i<G.numV;i++)
    {
		printf("%c",G.Vertex[i].data);
        p=G.Vertex[i].firstarc;
        while(p)
        {
			printf("->%2d%3d",p->adjvex,p->info);
            p=p->nextarc;
        }
     	printf("\n");
	}
}

然后是邻接矩阵的库 ljjz.h

/********************************************/
/*             邻接矩阵存储结构	   	 	    */
/********************************************/

#include 
#define Max 32767   			/*此处用32767代表无穷大*/
#define M 100          			/*最大顶点数*/
typedef char VertexType;  		/*顶点值类型*/
typedef struct{
	VertexType vertices[M];  /*顶点信息域*/
	int Edge[M][M]; 	     /*邻接矩阵*/
	int numV,numE;  	/*图中顶点总数与边数*/
} AdjMatrix;   			/*邻接矩阵表示的图类型*/

/* 函数功能:建立图的邻接矩阵 */ 
void creat(AdjMatrix *G, int n, int e)
{
	int i, j, vi, vj, w;      /*w为边的权值*/
	G->numV=n;
	G->numE=e;   	  
	printf("输入顶点的信息:\n");
	for( i=0; i<G->numV; i++ )
	{
    	printf("%d:",i+1);   
    	scanf("%c",&G->vertices[i] );
		getchar();     
	}
	for( i=0; i<G->numV; i++ )
	for( j=0; j<G->numV; j++ )
	{
		G->Edge[i][j]=Max;
		if(i==j)G->Edge[i][j]=0;
	}
	for( i=0; i<G->numE; i++ )
	{
  		printf("输入边的信息及权值(vi,vj,w):");  
  		scanf("%d,%d,%d",&vi,&vj,&w);
  		G->Edge[vi-1][vj-1]=w; 
  		G->Edge[vj-1][vi-1]=w;      /*对于无向图*/        
	}
}

/* 函数功能:输出图的邻接矩阵 */ 
void  print(AdjMatrix G)
{
	int i,j;
	printf ("输出顶点的信息:\n");
    for( i=0; i<G.numV; i++ )
		printf("%c ",G.vertices[i] );
    printf("\n输出图的邻接矩阵:\n" );
    for( i=0; i<G.numV; i++ )
	{
		for( j=0; j<G.numV ;j++ ) 
			printf("%6d",G.Edge[i][j] );
       	printf("\n");
	}
}

OK,开始做实验内容

任务1:图的建立和输出(保存文件为:学号-1.c)
(1)打开库文件“ljjz.h”(邻接矩阵存储)和“ljb.h”(邻接表存储),熟悉库中的相关函数。
(2)编写主函数输出下图的邻接矩阵或邻接表(自行选择一个完成)。
这里补充一下图【数据结构】图-创建图、求顶点度、Dijkstra算法求最短路径_第1张图片

#include "ljjz.h"
#include "ljb.h"
int main(){
	AdjMatrix aj;
	int n,e;
	printf("输入顶点");
	scanf("%d",&n);
	getchar();  
	printf("输入边数");
	scanf("%d",&e); 
	getchar();  
	creat(&aj,n,e);
	print(aj);
	return 0;
} 

这里的话,大概意思都差不多的,只不过是创建的是表还是矩阵的区别。

任务2:求图各顶点的度(保存文件为:学号-2.c)
编写函数void degree(AdjList G)输出以邻接表为存储结构的无向图的各顶点的度。

#include "ljb.h"
void degree(AdjList G){
	int i;
	for(i=0;i<G.numV;i++){
		int cnt =0;
		ArcNode *p =G.Vertex[i].firstarc;
		while(p){
			cnt++;
			p=p->nextarc;
		}
		printf("顶点%d的度为%d\n",i+1,cnt);
	}
}
int main(){
	AdjList G;
	int n;
	int e;
	printf("输入顶点:");
	scanf("%d",&n);getchar();
	printf("输入边:");
	scanf("%d",&e);getchar();
	creat(&G,n,e);
	print(G);
	degree(G);
	return 0;
}

任务3:求单源最短路径(保存文件为:学号-3.c)
采用邻接矩阵存储结构,编写函数void dijkstra(AdjMatrix G,int v)实现用Dijkstra算法求从某顶点v到其余各顶点的最短路径长度。
注:为简单起见,v的值为顶点在数组中的下标。

#include "ljjz.h"
int dist[M];int path[M];
void Dijkstra(AdjMatrix g, int v)
{
	int set[M];/*set[]为标记数组,set[Vi]=0表示Vi在T中,即没有被并入最短路径;
					 set[Vi]=1表示Vi在S中,即已经被并入最短路径。*/
	int min, i, j, u; 
	//对各数组初始化
	for (i = 0; i < g.numV; ++i)
	{
		dist[i] = g.Edge[v][i];
		set[i] = 0;
		if (g.Edge[v][i] < Max)
			path[i] = v;
		else
			path[i] = -1;
	}
	set[v] = 1; path[v] = -1;//初始化结
	for (i = 0; i < g.numV - 1; ++i)
	{
		min = Max;
		/*这个循环每次从剩余顶点中选出一个顶点,通往这个顶点的路径在通往所有剩余顶点的路径中
		是长度最短的*/
		for (j=0;j<g.numV;++j)
		{
			if (set[j] == 0 && dist[j] < min)
			{
				u = j;
				min = dist[j];
			}
		}
		set[u] = 1;//将选出的顶点并入最短路径中
		/*这个循环以刚并入的顶点作为中间点,对所有通往剩余顶点的路径进行检测*/
		for (j = 0; j < g.numV; ++j)
		{
			/*这个if语句判断顶点u的加入是否会出现通往顶点j的更短的路径,如果出现,则
			改变原来路径及其长度,否则什么都不做。*/
			if (set[j] == 0 && dist[u] + g.Edge[u][j] < dist[j])
			{
				dist[j] = dist[u] + g.Edge[u][j];
				path[j] = u;
			}
		}
	}
	for (i = 0; i < g.numV; i++)
	{
		printf("从%d到%d的最短路径长度为:%d\n",v+1,i+1,dist[i]);
	}
}
int main(){
	AdjMatrix G;
	int n,e;
	printf("请输入顶点数:");
	scanf("%d",&n);getchar();
	printf("请输入边数:");
	scanf("%d",&e);getchar();
	creat(&G,n,e);
	print(G);
	int v;
	printf("请输入要查询的顶点下标:");
	scanf("%d",&v);getchar();
	Dijkstra(G,v);
	int i;
	return 0;
} 

OK!实验完成!

你可能感兴趣的:(数据结构)