dijkstra算法笔记(C语言实现,显示路径)

dijkstra算法(迪杰斯特拉算法)笔记(C语言实现,显示路径)

具体描述每一步的运行情况

在学习完广度优先搜索之后,了解了在无权图中怎么找出最短路径。但广度优先搜索解决不了当边具有权值的情况。
dijkstra算法就是解决这种情况的算法。
一个具有边权的图:
在这里插入图片描述
现在,以1位初始点,找出各点到1的最短距离,并且显示路径。

首先创建一个结构数组,来储存各点的信息:

struct item{
	int key;      //这个点是否被访问 
	int dis;      //这个点到原点的距离 
	int n_number;  //路径中有多少个点 
	int n[10];    //创建数组来储存路径 
};
struct item dist[9]; //这个图中有9个点

从1开始,与1相连的2,8都没有被访问过,进入队列,并更新这些点的信息:
在这里插入图片描述

现在,队列头是2,于是2出队列,与2相关联且满足条件的进入队列(满足条件应分两种情况;1.若这个点没有被访问,直接进入队列。2.若这个点已经被访问,但新路径的距离比原路径的距离要短,这个点也入队,更新信息),更新各点的信息:
在这里插入图片描述
在上一步中,8虽然已经被访问过了,但更新之后8由路径(1-2-8)到1的距离为7,比之前的要小,所以点8的各项信息被更新,进入对列,所以现在队列中的(8,3,8)两个8具有一样的信息。
现在,与8相关的点进入队列,8出队列:更新后的信息:
在这里插入图片描述
继续操作,3出队,与3相关的点入队:
这里4,还没有被访问,直接入队,
9已经被访问,但9目前的距离为8,比12+2要小,9,不用入队。
在这里插入图片描述
现在,由于8已经被操作过,所以,8单纯出队,没有元素入队:
在这里插入图片描述
接着,7出队,6入队
在这里插入图片描述
接着,在9出队,且与9相连的点中,3满足更新条件(3目前距离为12,更新后为8+2=10),3入队:
在这里插入图片描述
4出队,5入队
在这里插入图片描述
至此所有元素都已经访问完毕,但队列并不为空,意味着仍然有元素可能会被更新
6出队,5满足更新条件,5入队
在这里插入图片描述
继续执行,3出队,4满足更新条件,入队:
在这里插入图片描述
接下来的两个5单纯出队,没有任何元素满足入队条件:
在这里插入图片描述
最后4出队,同样没有元素满足更新条件,没有元素入队,队列为空。算法结束。
最终结果如下:
在这里插入图片描述
代码与测试数据`

#include<stdlib.h>
#include<string.h>
#include<stdio.h>
struct node;
typedef struct node * pNode;
struct node{
	int num;
	int power;
	pNode next;
}; 
struct item{
	int key;      //这个点是否被访问 
	int dis;      //这个点到原点的距离 
	int n_number;  //路径中有多少个点 
	int n[10];    //创建数组来储存路径 
};
struct queue;
typedef struct queue * pQueue;
struct queue{
	int num;
	pQueue next;
};
pQueue add(pQueue,pQueue);
pQueue out(pQueue);
void show(pNode *,int);
int main()
{
	pNode * list;
	int a,b,c,N,i,j;
	pNode current,temp;
	scanf("%d",&N);
	list=(pNode *)malloc(sizeof(pNode)*N);
	for(i=0;i<N;i++){
		list[i]=(pNode)malloc(sizeof(struct node));
		temp=list[i];
		temp->num=i+1;
		temp->next=NULL;
		while(scanf("%d",&a)==1){
			current=(pNode)malloc(sizeof(struct node));
			current->num=a;
			scanf("%d",&b);
			current->power=b;
			current->next=NULL;
			temp->next=current;
			temp=current;
		}
		getchar();
	}
	show(list,N);
	//储存完毕,开始搜索
	struct item dist[N];
	for(i=0;i<N;i++){
		dist[i].key=0;
		dist[i].dis=0;
		dist[i].n_number=0;
	}
	//以第一个点为初始点
	dist[0].key=1;
	dist[0].dis=0;
	int dis=0 ,count=1,x[10];
	x[0]=1;
	pQueue head=NULL,kong;
	current=list[0]->next;
	do{
		while(current!=NULL){
			if(dist[current->num-1].key==0){//第一次遇到,直接入队 
				dist[current->num-1].key=1;
				dist[current->num-1].dis=dis+current->power;
				kong=(pQueue)malloc(sizeof(struct queue));
				kong->num=current->num;
				head=add(head,kong);
				//开始复制数组;
				for(i=0;i<count;i++)
					dist[current->num-1].n[i]=x[i];
				dist[current->num-1].n[count]=current->num;
				dist[current->num-1].n_number=count+1; 
			}
			else if(dist[current->num-1].dis>dis+current->power){
				dist[current->num-1].dis=dis+current->power;
				kong=(pQueue)malloc(sizeof(struct queue));
				kong->num=current->num;
				head=add(head,kong);
				//开始复制数组;
				for(i=0;i<count;i++)
					dist[current->num-1].n[i]=x[i];
				dist[current->num-1].n[count]=current->num;
				dist[current->num-1].n_number=count+1; 
			}
			current=current->next;
		}
		current=list[head->num-1]->next;
		count=dist[head->num-1].n_number;
		for(i=0;i<count;i++)
			x[i]=dist[head->num-1].n[i];
		dis=dist[head->num-1].dis;
		head=out(head);
		while(current!=NULL){
			if(dist[current->num-1].key==0){//第一次遇到,直接入队 
				dist[current->num-1].key=1;
				dist[current->num-1].dis=dis+current->power;
				kong=(pQueue)malloc(sizeof(struct queue));
				kong->num=current->num;
				head=add(head,kong);
				//开始复制数组;
				for(i=0;i<count;i++)
					dist[current->num-1].n[i]=x[i];
				dist[current->num-1].n[count]=current->num;
				dist[current->num-1].n_number=count+1; 
			}
			else if(dist[current->num-1].dis>dis+current->power){
				dist[current->num-1].dis=dis+current->power;
				kong=(pQueue)malloc(sizeof(struct queue));
				kong->num=current->num;
				head=add(head,kong);
				//开始复制数组;
				for(i=0;i<count;i++)
					dist[current->num-1].n[i]=x[i];
				dist[current->num-1].n[count]=current->num;
				dist[current->num-1].n_number=count+1; 
			}
			current=current->next;
		}
	}while(head!=NULL);
	for(i=0;i<N;i++){
		if(dist[i].dis==0){
			printf("元素:%d  原点",i+1);
		}
		else{
			printf("元素:%d  距离:%d",i+1,dist[i].dis);
			printf("  路径:");
			for(j=0;j<dist[i].n_number;j++){
				printf("%d--",dist[i].n[j]);
			}
			printf("\n");
		}
	}
}
void show(pNode *list,int N)
{
	int i;
	pNode current;
	for(i=0;i<N;i++)
	{
		printf("%d -> ",list[i]->num);
		current=list[i]->next;
		while(current!=NULL){
			printf("%d(%d) ",current->num,current->power);
			current=current->next;
		}
		puts("");
	}
}
pQueue out(pQueue head)
{
	if(head->next==NULL){
		free(head);
		return NULL;
	}
	else{
		pQueue temp=head->next;
		free(head);
		return temp;
	}
}
pQueue add(pQueue head,pQueue current)
{
	if(head==NULL){
		head=current;
		current->next=NULL;
	}
	else{
		pQueue temp=head;
		while(temp->next!=NULL)
			temp=temp->next;
		temp->next=current;
		current->next=NULL;
	}
	return head;
}

测试数据:

9
2 4 8 8 +
1 4 8 3 3 8 +
2 8 9 2 4 7 +
3 7 6 14 5 9 +
4 9 6 10 +
4 14 5 10 7 2 +
6 2 9 6 8 6 +
7 6 9 1 2 3 1 8 +
3 2 7 6 8 1 +

以输入非数字符号结束,所以后面有一个加号
以散列表(那个形式,没有散列函数)储存图的结构:
1 -> :2(4) 8(8)
2 -> :1(4) 8(3) 3(8)
3 -> :2(8) 9(2) 4(7)
4 -> :3(7) 6(14) 5(9)
5 -> :4(9) 6(10)
6 -> :4(14) 5(10) 7(2)
7 -> :6(2) 9(6) 8(6)
8 -> :7(6) 9(1) 2(3) 1(8)
9 -> :3(2) 7(6) 8(1)
最后的输出结果:
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值