迪杰斯特拉算法

#include <stdio.h>
#include <string.h>
#define OK 1
#define INFINITY 32767
#define MAX_VERTEX_NUM 30
#define MAXINFOLEN 30
#define ERROR 0
#define OVERFLOW -1
#define MAXVERTEXLEN 30
#define FALSE 0
#define TRUE 1
typedef int Status;
typedef enum { DG, DN, UDG, UDN }GraphKind;
typedef int VRType;
typedef int InfoType;
typedef char* VertexType;

typedef struct ArcCell
{
	VRType adj;
	InfoType* info;
}ArcCell, AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
typedef struct
{
	VertexType vexs[MAX_VERTEX_NUM];
	AdjMatrix arcs;
	int vexnum, arcnum;
	GraphKind kind;
}MGraph;
Status CreatGraph(MGraph* G)
{
	printf("请输入图的类型\n");
	scanf("%d", &(G->kind));
	switch (G->kind)
	{
	case DG:return(CreatDG(G)); break;
	case DN:return(CreatDN(G)); break;
	case UDG:return(CreatUDG(G)); break;
	case UDN:return(CreatUDN(G)); break;
	default: return ERROR;
	}
}
Status CreatDG(MGraph* G)
{
	printf("请依次输入图的总结点数,弧数,以及是弧是否需要额外信息,无额外信息输入0,有额外信息输入1\n");
	int info;
	scanf("%d%d%d", &(G->vexnum), &(G->arcnum), &info);
	getchar();
	printf("请输入%d个顶点的描述\n", G->vexnum);
	for (int i = 0; i < G->vexnum; i++)
	{
		G->vexs[i] = (VertexType)malloc(sizeof(char) * MAXVERTEXLEN);
		if (!G->vexs[i]) exit(OVERFLOW);
		gets(G->vexs[i]);
	}
	for(int i=0;i<G->vexnum;i++)
		for (int j = 0; j < G->vexnum; j++)
		{
			G->arcs[i][j].adj = 0;
			G->arcs[i][j].info = NULL;
		}
	int tail, head;
	char* ch;
	ch = (char*)malloc(sizeof(char) * MAXVERTEXLEN);
	if (!ch) exit(OVERFLOW);
	for (int i = 0; i < G->arcnum; i++)
	{
		printf("请输入第%d个顶点关系\n", i + 1);
		printf("请输入它的弧尾顶点描述\n");
		gets(ch);
		for (int j = 0; j < G->vexnum; j++)
			if (strcmp(ch, G->vexs[j]) == 0)
			{
				tail = j;
				break;
			}
		printf("请输入它的弧头顶点描述\n");
		gets(ch);
		for (int j = 0; j < G->vexnum; j++)
			if (strcmp(ch, G->vexs[j]) == 0)
			{
				head = j;
				break;
			}
		G->arcs[tail][head].adj = 1;
		if (info)
		{
			G->arcs[tail][head].info = (InfoType*)malloc(sizeof(InfoType) * MAXINFOLEN);
			if (!G->arcs[tail][head].info) exit(OVERFLOW);
			printf("请输入其信息\n");
			gets(G->arcs[tail][head].info);
		}
	}
	return OK;
}
Status CreatDN(MGraph* G)
{
	printf("请依次输入图的总结点数,弧数,以及是弧是否需要额外信息,无额外信息输入0,有额外信息输入1\n");
	int info;
	scanf("%d%d%d", &(G->vexnum), &(G->arcnum), &info);
	getchar();
	printf("请输入%d个顶点的描述\n", G->vexnum);
	for (int i = 0; i < G->vexnum; i++)
	{
		G->vexs[i] = (VertexType)malloc(sizeof(char) * MAXVERTEXLEN);
		if (!G->vexs[i]) exit(OVERFLOW);
		gets(G->vexs[i]);
	}
	for (int i = 0; i < G->vexnum; i++)
		for (int j = 0; j < G->vexnum; j++)
		{
			G->arcs[i][j].adj = INFINITY;
			G->arcs[i][j].info = NULL;
		}
	int tail, head;
	char* ch;
	ch = (char*)malloc(sizeof(char) * MAXVERTEXLEN);
	if (!ch) exit(OVERFLOW);
	for (int i = 0; i < G->arcnum; i++)
	{
		printf("请输入第%d个顶点关系\n", i + 1);
		printf("请输入它的弧尾顶点描述\n");
		gets(ch);
		for (int j = 0; j < G->vexnum; j++)
			if (strcmp(ch, G->vexs[j]) == 0)
			{
				tail = j;
				break;
			}
		printf("请输入它的弧头顶点描述\n");
		gets(ch);
		for (int j = 0; j < G->vexnum; j++)
			if (strcmp(ch, G->vexs[j]) == 0)
			{
				head = j;
				break;
			}
		printf("请输入弧的权值\n");
		scanf("%d", &(G->arcs[tail][head]));
		getchar();
		if (info)
		{
			G->arcs[tail][head].info = (InfoType*)malloc(sizeof(InfoType) * MAXINFOLEN);
			if (!G->arcs[tail][head].info) exit(OVERFLOW);
			printf("请输入其信息\n");
			gets(G->arcs[tail][head].info);
		}
	}
	return OK;
}
Status CreatUDG(MGraph* G)
{
	printf("请依次输入图的总结点数,弧数,以及是弧是否需要额外信息,无额外信息输入0,有额外信息输入1\n");
	int info;
	scanf("%d%d%d", &(G->vexnum), &(G->arcnum), &info);
	getchar();
	printf("请输入%d个顶点的描述\n", G->vexnum);
	for (int i = 0; i < G->vexnum; i++)
	{
		G->vexs[i] = (VertexType)malloc(sizeof(char) * MAXVERTEXLEN);
		if (!G->vexs[i]) exit(OVERFLOW);
		gets(G->vexs[i]);
	}
	for (int i = 0; i < G->vexnum; i++)
		for (int j = 0; j < G->vexnum; j++)
		{
			G->arcs[i][j].adj = 0;
			G->arcs[i][j].info = NULL;
		}
	int vex1, vex2;
	char* ch;
	ch = (char*)malloc(sizeof(char) * MAXVERTEXLEN);
	if (!ch) exit(OVERFLOW);
	for (int i = 0; i < G->arcnum; i++)
	{
		printf("请输入第%d个顶点关系\n", i + 1);
		printf("请输入它所依附的第一个顶点的顶点描述\n");
		gets(ch);
		for (int j = 0; j < G->vexnum; j++)
			if (strcmp(ch, G->vexs[j]) == 0)
			{
				vex1 = j;
				break;
			}
		printf("请输入它所依附的第二个顶点的顶点描述\n");
		gets(ch);
		for (int j = 0; j < G->vexnum; j++)
			if (strcmp(ch, G->vexs[j]) == 0)
			{
				vex2 = j;
				break;
			}
		G->arcs[vex1][vex2].adj = 1;
		G->arcs[vex2][vex1].adj = 1;
		if (info)
		{
			G->arcs[vex1][vex2].info = (InfoType*)malloc(sizeof(InfoType) * MAXINFOLEN);
			if (!G->arcs[vex1][vex2].info) exit(OVERFLOW);
			printf("请输入其信息\n");
			gets(G->arcs[vex1][vex2].info);
			G->arcs[vex2][vex1].info = (InfoType*)malloc(sizeof(InfoType) * MAXINFOLEN);
			if (!G->arcs[vex2][vex1].info) exit(OVERFLOW);
			strcpy(G->arcs[vex2][vex1].info, G->arcs[vex1][vex2].info);
		}
	}
	return OK;
}
Status CreatUDN(MGraph* G)
{
	printf("请依次输入图的总结点数,弧数,以及是弧是否需要额外信息,无额外信息输入0,有额外信息输入1\n");
	int info;
	scanf("%d%d%d", &(G->vexnum), &(G->arcnum), &info);
	getchar();
	printf("请输入%d个顶点的描述\n", G->vexnum);
	for (int i = 0; i < G->vexnum; i++)
	{
		G->vexs[i] = (VertexType)malloc(sizeof(char) * MAXVERTEXLEN);
		if (!G->vexs[i]) exit(OVERFLOW);
		gets(G->vexs[i]);
	}
	for (int i = 0; i < G->vexnum; i++)
		for (int j = 0; j < G->vexnum; j++)
		{
			G->arcs[i][j].adj = INFINITY;
			G->arcs[i][j].info = NULL;
		}
	int vex1, vex2;
	char* ch;
	ch = (char*)malloc(sizeof(char) * MAXVERTEXLEN);
	if (!ch) exit(OVERFLOW);
	for (int i = 0; i < G->arcnum; i++)
	{
		printf("请输入第%d个顶点关系\n", i + 1);
		printf("请输入它所依附的第一个顶点的顶点描述\n");
		gets(ch);
		for (int j = 0; j < G->vexnum; j++)
			if (strcmp(ch, G->vexs[j]) == 0)
			{
				vex1 = j;
				break;
			}
		printf("请输入它所依附的第二个顶点的顶点描述\n");
		gets(ch);
		for (int j = 0; j < G->vexnum; j++)
			if (strcmp(ch, G->vexs[j]) == 0)
			{
				vex2 = j;
				break;
			}
		printf("请输入此弧权值\n");
		scanf("%d", &(G->arcs[vex1][vex2].adj));
		getchar();
		G->arcs[vex2][vex1].adj = G->arcs[vex1][vex2].adj;
		if (info)
		{
			G->arcs[vex1][vex2].info = (InfoType*)malloc(sizeof(InfoType) * MAXINFOLEN);
			if (!G->arcs[vex1][vex2].info) exit(OVERFLOW);
			printf("请输入其信息\n");
			gets(G->arcs[vex1][vex2].info);
			G->arcs[vex2][vex1].info = (InfoType*)malloc(sizeof(InfoType) * MAXINFOLEN);
			if (!G->arcs[vex2][vex1].info) exit(OVERFLOW);
			strcpy(G->arcs[vex2][vex1].info, G->arcs[vex1][vex2].info);
		}
	}
	return OK;
}


//迪杰斯特拉算法求最短路径
typedef int** PathMatrix;
typedef int* ShortPathTable;
void ShortestPath_DIJ(MGraph G, char* ch, PathMatrix* P, ShortPathTable* D)
{
	int st;
	for(int i=0;i<G.vexnum;i++)
		if (strcmp(ch, G.vexs[i]) == 0)
		{
			st = i;
			break;
		}
	*P = (int**)malloc(sizeof(int*) * G.vexnum);
	if (!*P) exit(OVERFLOW);
	for (int i = 0; i < G.vexnum; i++)
	{
		(*P)[i] = (int*)malloc(sizeof(int) * G.vexnum);
		if (!(*P)[i]) exit(OVERFLOW);
	}
	*D = (int*)malloc(sizeof(int) * G.vexnum);
	if (!*D) exit(OVERFLOW);
	for (int i = 0; i < G.vexnum; i++)
		for (int j = 0; j < G.vexnum; j++)
			(*P)[i][j] = 0;
	for (int i = 0; i < G.vexnum; i++)
	{
		if (G.arcs[st][i].adj < INFINITY)
			(*P)[i][i] = 1;
	}
	for (int i = 0; i < G.vexnum; i++)
		(*D)[i] = G.arcs[st][i].adj;
	int count = 1;
	int* visit;
	visit = (int*)malloc(sizeof(int) * G.vexnum);
	if (!visit) exit(OVERFLOW);
	for (int i = 0; i < G.vexnum; i++)
		visit[i] = 0;
	visit[st] = 1;
	while (count <= G.vexnum - 1)
	{
		int mincost = INFINITY, min;
		for (int i = 0; i < G.vexnum; i++)
			if (!visit[i] && (*D)[i] < mincost)
			{
				min = i;
				mincost = (*D)[i];
			}
		for (int i = 0; i < G.vexnum; i++)
		{
			if (!visit[i] && G.arcs[min][i].adj != INFINITY && (*D)[i] > (*D)[min] + G.arcs[min][i].adj)
			{
				(*D)[i] = (*D)[min] + G.arcs[min][i].adj;
				for (int j = 0; j < G.vexnum; j++)
					(*P)[i][j] = (*P)[min][j];
				(*P)[i][i] = 1;
			}
		}
		visit[min] = 1;
		count++;
	}
}
//迪杰斯特拉算法主函数
int main()
{
	PathMatrix P;
	ShortPathTable D;
	MGraph G;
	CreatGraph(&G);
	char* ch;
	ch = (char*)malloc(sizeof(char) * MAXVERTEXLEN);
	if (!ch) exit(OVERFLOW);
    printf("请输入起始地点\n");
	gets(ch);
	ShortestPath_DIJ(G, ch, &P, &D);
	for (int i = 0; i < G.vexnum; i++)
	{
		for (int j = 0; j < G.vexnum; j++)
			printf("%d  ", P[i][j]);
		printf("\n");
	}
	int st;
	for (int i = 0; i < G.vexnum; i++)
		if (strcmp(ch, G.vexs[i]) == 0)
		{
			st = i;
			break;
		}
	int count = 1;
	for (int i = 0; i < G.vexnum; i++)
	{
		if (st != i)
		{
			printf("*******************************************************\n\n");
			printf("<%d>到%s:%d\n", count, G.vexs[i], D[i]);
			int j = st;
			while (j != i)
			{
				printf("%s->", G.vexs[j]);
				for (int k = 0; k < G.vexnum; k++)
				{
					if (P[i][k] && G.arcs[j][k].adj != INFINITY)
					{
						P[i][k] = 0;
						j = k;
						break;
					}
				}
			}
			printf("%s\n\n", G.vexs[i]);
			count++;
		}
	}
	printf("*******************************************************\n");
	return 0;
}

输入:(以大连为起始地点)

3
25 30 0
哈尔滨
长春
沈阳
大连
天津
北京
徐州
郑州
呼和浩特
兰州
西安
西宁
乌鲁木齐
上海
武汉
成都
昆明
贵阳
株洲
南昌
福州
柳州
南宁
广州
深圳
哈尔滨
长春
242
长春
沈阳
305
沈阳
大连
397
沈阳
天津
704
天津
徐州
674
天津
北京
137
北京
郑州
695
郑州
徐州
349
北京
呼和浩特
668
呼和浩特
兰州
1145
兰州
西安
676
西安
郑州
511
兰州
西宁
216
兰州
乌鲁木齐
1892
西安
成都
842
成都
贵阳
967
贵阳
株洲
902
株洲
武汉
409
武汉
郑州
534
株洲
南昌
367
南昌
上海
825
上海
徐州
651
成都
昆明
1100
昆明
贵阳
639
贵阳
柳州
607
柳州
株洲
672
柳州
南宁
255
株洲
广州
675
广州
深圳
140
南昌
福州
622
大连

原图:

 

结果:

1.P矩阵输出(行的序号所代表的地点是终点,列所代表的地点如果为1,意味着大连到终点的最短路径需要经过此地)

 2.部分地点输出

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值