圖-Dijkstra迪傑斯特拉算法

問題:找出如下圖中v0 到各點的最短距離,並輸出距離及路徑
在這裏插入圖片描述

程序運行截圖:
在這裏插入圖片描述
分析:
在圖中找到V0到各點的最小短距離路徑:** 使用dijkstra算法求單源最短路徑**

  • 用dist[]數組來存儲v0到各點的最短距離,path[]來存儲路徑,path[w]= v即w點經過v,collected[]記錄該點是否被收入s
  • 第一步:初始化,所有dist設置爲無窮大,path設置爲-1
  • 第二步:進入主循環前,v0的鄰接點初始化,path和dist初始化,再將v0併入S集
  • 第三步:進入主循環,在未收錄的找到v0到其餘n-1個頂點最短路徑的頂點,併入S,如果找不到這樣的點,退出循環
  • 第四步:遍歷v的每個鄰接點,更新當前最短路徑及距離

dijkstra函數

void Dijkstra(MGraph N, int v0, PathMatrix path, ShortPathLength dist)
/*在圖中找到V0到各點的最小短距離路徑*/
{
	int i,v,w;
	int min;//最短路徑
	int collected[MaxSize];//存儲頂點是否收錄到S
	for (v = 0; v < N.vexnum; v++) // 初始化v0到v的距離,
	{
		if (N.arc[v0][v].adj < INFINITY)//鄰接點
		{
			path[v] = 0;
			dist[v] = N.arc[v0][v].adj;
		}
		else
		{
			path[v] = -1;
			dist[v] = INFINITY;
		}
		collected[v] = 0;
	}

	collected[v0] = 1;//先將v0併入s
	dist[v0] = 0;
	//path[0] = 0;
	//開始主循環
	while (1)
	{
		v = 0;
		min = INFINITY;
		for (w = 0; w < N.vexnum ; w++) //在未收錄的頂點中找到距離最小的頂點
		{
			if(collected[w] == 0)
				if (dist[w] < min)
				{
					v = w;
					min = dist[w];
				}
		}
		if (v == 0) //如果這樣的v不存在
			break;
		collected[v] = 1;//將該併入s


		for (w = 0; w < N.vexnum ; w++) ////在V的鄰接點中更新當前最短路徑及距離
		{
			if(N.arc[v][w].adj < INFINITY)
				if (collected[w] == 0)
					if (dist[v] + N.arc[v][w].adj < dist[w])
					{
						dist[w] = dist[v] + N.arc[v][w].adj;
						path[w] = v;
					}
		}
	}
	

}

所有代碼


#include "pch.h"
#include <iostream>
#include<stdio.h>
#include<stdlib.h>

typedef char VertexType; //相當於VertexType 爲char[4]
#define INFINITY 65535 //最大值
#define MaxSize 50 //最大頂點個數
typedef enum{DG,DN,UDG,UDN}GrandKind;//有向圖,有向網,無向圖,無向網
typedef int VRType; //頂點關係類型,無權圖用0或1,有權圖,則爲權值類型
typedef char InfoPtr;

typedef struct
{
	VRType adj;//對於無權圖用0或1表示,1表示相鄰,0表示不相鄰;對於帶權值得圖存儲權值
	InfoPtr * info;//該弧相關信息指針,與弧或邊的相關信息
} ArcNode, AdjMatrix[MaxSize][MaxSize];

typedef struct //圖的類型定義
{
	VertexType vex[MaxSize][4];//相當於char[MaxSize][4],用於儲存頂點
	AdjMatrix arc; // 鄰接矩陣,存儲邊或弧的信息
	int vexnum, arcnum;//頂點數和弧的數目
	GrandKind kind;//圖的定義
}MGraph;


typedef int PathMatrix[MaxSize];//保存最短路徑的數組
typedef int ShortPathLength[MaxSize];//定義一個保存從頂點到V的最短距離的數組

void CreateGraph(MGraph *N);
int LocateVertex(MGraph N, VertexType *v);
void DestroyGraph(MGraph *N);
void DisplayGraph(MGraph N);
void Dijkstra(MGraph N, int v0, PathMatrix path, ShortPathLength dist);//Dijkstra算法

void PrintPath(MGraph N, int v, PathMatrix path)//遞歸打印路徑
{
	/*if (v != 0)
	{
		printf("-%s", N.vex[path[v]]);
		PrintPath(N, path[v], path);
	}
	else
		return;*/
	
	while (v!=-1)
	{
		
			printf("%s-", N.vex[v]);
			v = path[v];
		
	}

}

int main()
{
	MGraph N;
	ShortPathLength dist;
	PathMatrix path;
	int i;

	printf("創建有向網:\n");
	CreateGraph(&N);
	DisplayGraph(N);
	//DestroyGraph(&N);
	Dijkstra(N, 0, path, dist);
	printf("頂點%s到各個頂點的最短距離:\n", N.vex[0]);
	for (i = 0; i < N.vexnum; i++)
	{
		printf("%s--%s:  dist = %d \n", N.vex[0], N.vex[i], dist[i]);
		printf("路徑:");
		PrintPath(N, i, path);
		//printf("%s", N.vex[0]);
		printf("\n");
	}


	return 0;
}

void CreateGraph(MGraph *N)
//
{
	int i,j,k,weight;
	VertexType v1[4], v2[4];
	printf("請輸入有向網的頂點數和弧數(以逗號分開):\n");
	scanf_s("%d,%d", &(N->vexnum), &(N->arcnum));
	printf("請輸入%d個頂點的值(<%d個字符)\n", N->vexnum, MaxSize);
	for (i = 0; i < N->vexnum; i++)//存儲頂點
	{
		scanf_s("%s", N->vex[i],sizeof(N->vex[0]));
	}

	for (i = 0; i < N->vexnum; i++)// 初始化鄰接矩陣
	{
		for (j = 0; j < N->vexnum; j++)
		{
			N->arc[i][j].adj = INFINITY;
			N->arc[i][j].info = NULL;
		}
	}

	printf("輸入兩個頂點和弧的權值(以空格隔開):\n");
	for (k = 0; k < N->arcnum; k++)
	{
		scanf_s("%s %s %d", v1,sizeof(4), v2,sizeof(4) ,&weight);
		i = LocateVertex(*N, v1);//找到弧尾頂點的下標
		j = LocateVertex(*N, v2);//找到弧頂頂點的下標
		N->arc[i][j].adj = weight;

	}
	N->kind = DN; //類型爲有向網

}

int LocateVertex(MGraph N, VertexType *v)
//定位
{
	int  i;
	for (i = 0; i < N.vexnum; i++)
	{
		if (strcmp(N.vex[i],v)== 0)
			return i;
	}
	return -1;
}

void DestroyGraph(MGraph *N)
//銷燬鄰接表
{
	int i, j;
	for (i = 0; i < N->vexnum; i++)
	{
		for (j = 0; j < N->vexnum; j++)
		{
			if (N->arc[i][j].info != NULL)
			{
				free(N->arc[i][j].info);
				N->arc[i][j].info = NULL;
			}
		}
	}
	N->arcnum = N->vexnum = 0;

}

void DisplayGraph(MGraph N)
//顯示鄰接表
{
	int i, j, k;
	printf("輸出網的結點和弧:\n");
	printf("該網有%d個頂點,%d條弧\n",N.vexnum,N.arcnum);
	printf("頂點依次是:");
	for (i = 0; i < N.vexnum;i++)
	{
		printf("%s ", N.vex[i]);
	}
	printf("網:\n");
	printf("i=    ");
	for (i = 0; i < N.vexnum; i++)
	{
		printf("%8d", i);
	}
	printf("\n");
	for (i = 0; i < N.vexnum; i++)
	{
		printf("%8d", i);
		for (j = 0; j < N.vexnum; j++)
		{
			printf("%8d", N.arc[i][j].adj);
		}
		printf("\n");
	}

}

void Dijkstra(MGraph N, int v0, PathMatrix path, ShortPathLength dist)
/*在圖中找到V0到各點的最小短距離路徑*/
{
	int i,v,w;
	int min;//最短路徑
	int collected[MaxSize];//存儲頂點是否收錄到S
	for (v = 0; v < N.vexnum; v++) // 初始化v0到v的距離,
	{
		if (N.arc[v0][v].adj < INFINITY)//鄰接點
		{
			path[v] = 0;
			dist[v] = N.arc[v0][v].adj;
		}
		else
		{
			path[v] = -1;
			dist[v] = INFINITY;
		}
		collected[v] = 0;
	}

	collected[v0] = 1;//先將v0併入s
	dist[v0] = 0;
	//path[0] = 0;
	//開始主循環
	while (1)
	{
		v = 0;
		min = INFINITY;
		for (w = 0; w < N.vexnum ; w++) //在未收錄的頂點中找到距離最小的頂點
		{
			if(collected[w] == 0)
				if (dist[w] < min)
				{
					v = w;
					min = dist[w];
				}
		}
		if (v == 0) //如果這樣的v不存在
			break;
		collected[v] = 1;//將該併入s


		for (w = 0; w < N.vexnum ; w++) ////在V的鄰接點中更新當前最短路徑及距離
		{
			if(N.arc[v][w].adj < INFINITY)
				if (collected[w] == 0)
					if (dist[v] + N.arc[v][w].adj < dist[w])
					{
						dist[w] = dist[v] + N.arc[v][w].adj;
						path[w] = v;
					}
		}
	}
	

}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章