首先是邻接表的库 ljb.h
/*********************************************/
/* 邻接表存储结构 */
/*********************************************/
#include <stdio.h>
#include <stdlib.h>
#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 <stdio.h>
#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)编写主函数输出下图的邻接矩阵或邻接表(自行选择一个完成)。
这里补充一下图
#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!实验完成!