Diskstra算法

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

简介
Dijkstra(迪杰斯特拉)算法是典型的单源最短路径算法,用于计算一个节点到其他所有节点的最短路径。主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止。Dijkstra算法是很有代表性的最短路径算法,在很多专业课程中都作为基本内容有详细的介绍,如数据结构,图论,运筹学等等。Dijkstra一般的表述通常有两种方式,一种用永久和临时标号方式,一种是用OPEN, CLOSE表的方式,这里均采用永久和临时标号的方式。注意该算法要求图中不存在负权边。
编辑本段算法描述
(这里描述的是从节点1开始到各点的dijkstra算法,其中Wa->b表示a->b的边的权值,d(i)即为最短路径值) 1. 置集合S={2,3,...n}, 数组d(1)=0, d(i)=W1->i(1,i之间存在边) or +无穷大(1.i之间不存在边) 2. 在S中,令d(j)=min{d(i),i属于S},令S=S-{j},若S为空集则算法结束,否则转3 3. 对全部i属于S,如果存在边j->i,那么置d(i)=min{d(i), d(j)+Wj->i},转2
编辑本段复杂度分析
Dijkstra 算法的时间复杂度为O(n^2) 空间复杂度取决于存储方式,邻接矩阵为O(n^2)
编辑本段算法实现
输入输出格式
输入格式: 第1行:一个数n,代表有n个节点 第2-n+1行:每行n个数,代表图的邻接矩阵,没有边相连为-1 输出格式: 第1行:n-1个数,分别是1号节点到2-n号节点的最短路径
C++
#include #include using namespace std; const int MaxNum=1000000; //边权最大值 int n; //节点数目 int dist[501]; //到节点1的最短路径值 bool state[501]; //节点被搜索过状态指示 int data[501][501]; //邻接矩阵 //查找权值最小的节点 int findmin() { int minnode=0, min=MaxNum; for(int i=1; i<=n; i++) if ((dist[i]> n; for(int p=1; p<=n; p++) for(int q=1; q<=n; q++) { in >> data[p][q]; if (data[p][q]==0) data[p][q]=MaxNum; } //初始化 for(int i=1; i<=n; i++) dist[i]=data[1][i]; state[1]=true; int done=1; while (donedist[node]+data[node][i]) && (!state[i])) dist[i]=dist[node]+data[node][i]; } else break; } for(int p=1; p<=n; p++) { if (dist[p]==MaxNum) out<<-1;

 else out<Pascal
program dijkstra; var state:array[1..100]of boolean; data:array[1..100,1..100]of longint; n,i,j,k,min,node:longint; begin assign(input,'dijkstra.in'); assign(output,'dijkstra.out'); reset(input); rewrite(output); fillchar(data, sizeof(data), 0); fillchar(state,sizeof(state),0); readln(n); for i:=1 to n do for j:=1 to n do begin read(data[i,j]); if data[i,j]=0 then data[i,j]:=maxint; end; state[1]:=true; for k:=2 to n do begin min:=maxint; {查找权值最小的点为node} node:=1; for i:=2 to n do if (data[1,i]maxint then write(data[1,i],' ') else write(-1,' '); writeln(data[1,n]); close(input); close(output); end.
测试样例
Sample Input 7 00 20 50 30 00 00 00 20 00 25 00 00 70 00 50 25 00 40 25 50 00 30 00 40 00 55 00 00 00 00 25 55 00 10 00 00 70 50 00 10 00 00 00 00 00 00 00 00 00 Sample Output -1 20 45 30 70 80 -1
编辑本段大概过程
创建两个表,OPEN, CLOSE。 OPEN表保存所有已生成而未考察的节点,CLOSED表中记录已访问过的节点。 1. 访问路网中里起始点最近且没有被检查过的点,把这个点放入OPEN组中等待检查。 2. 从OPEN表中找出距起始点最近的点,找出这个点的所有子节点,把这个点放到CLOSE表中。 3. 遍历考察这个点的子节点。求出这些子节点距起始点的距离值,放子节点到OPEN表中。 4. 重复2,3,步。直到OPEN表为空,或找到目标点。 /* Dijkstra.c Copyright (c) 2002, 2006 by ctu_85 All Rights Reserved. */ #include "stdio.h" #include "malloc.h" #define maxium 32767 #define maxver 9 /*defines the max number of vertexs which the programm can handle*/ #define OK 1 struct Point { char vertex【3】; struct Link *work; struct Point *next; }; struct Link { char vertex【3】; int value; struct Link *next; }; struct Table /*the workbannch of the algorithm*/ { int cost; int Known; char vertex【3】; char path【3】; struct Table *next; }; int Dijkstra(struct Point *,struct Table *); int PrintTable(int,struct Table *

); int PrintPath(int,struct Table *,struct Table *); struct Table * CreateTable(int,int); struct Point * FindSmallest(struct Table *,struct Point *);/*Find the vertex which has the smallest value reside in the table*/ int main() { int i,j,num,temp,val; char c; struct Point *poinpre,*poinhead,*poin; struct Link *linpre,*linhead,*lin; struct Table *tabhead; poinpre=poinhead=poin=(struct Point *)malloc(sizeof(struct Point)); poin->next=NULL; poin->work=NULL; restart: printf("Notice:if you wanna to input a vertex,you must use the format of number!\n"); printf("Please input the number of points:\n"); scanf("%d",&num); if(num>maxver||num<1||num%1!=0) { printf("\nNumber of points exception!"); goto restart; } for(i=0;i { printf("Please input the points next to point %d,end with 0:\n",i+1); poin=(struct Point *)malloc(sizeof(struct Point)); poinpre->next=poin; poin->vertex【0】='v'; poin->vertex【1】='0'+i+1; poin->vertex【2】='\0'; linpre=lin=poin->work; linpre->next=NULL; for(j=0;j { printf("The number of the %d th vertex linked to vertex %d:",j+1,i+1); scanf("%d",&temp); if(temp==0) { lin->next=NULL; break; } else { lin=(struct Link *)malloc(sizeof(struct Link)); linpre->next=lin; lin->vertex【0】='v'; lin->vertex【1】='0'+temp; lin->vertex【2】='\0'; printf("Please input the value betwixt %d th point towards %d th point:",i+1,temp); scanf("%d",&val); lin->value=val; linpre=linpre->next; lin->next=NULL; } } poinpre=poinpre->next; poin->next=NULL; } printf("Please enter the vertex where Dijkstra algorithm starts:\n"); scanf("%d",&temp); tabhead=CreateTable(temp,num); Dijkstra(poinhead,tabhead); PrintTable(temp,tabhead); return OK; } struct Table * CreateTable(int vertex,int total) { struct Table *head,*pre,*p; int i; head=pre=p=(struct Table *)malloc(sizeof(struct Table)); p->next=NULL; for(i=0;i { p=(struct Table *)malloc(sizeof(struct Table)); pre->next=p; if(i+1==vertex) { p->vertex【0】='v'; p->vertex【1】='0'+i+1; p->vertex【2】='\0'; p->cost=0; p->Known=0; } else { p->vertex【0】='v'; p->vertex【1】='0'+i+1; p->vertex【2】='\0'; p->cost=maxium; p->Known=0; } p->next=NULL; pre=pre->next; } return head; } int Dijkstra(struct Point *p1,struct Table *p2) /* Core of the programm*/ { int costs; char temp; struct Point *poinhead=p1,*now; struct Link *linna; struct Table *tabhead=p2,*searc,*result; while(1) { now=FindSmalles

t(tabhead,poinhead); if(now==NULL) break; result=p2; result=result->next; while(result!=NULL) { if(result->vertex【1】==now->vertex【1】) break; else result=result->next; } linna=now->work->next; while(linna!=NULL) /* update all the vertexs linked to the signed vertex*/ { temp=linna->vertex【1】; searc=tabhead->next; while(searc!=NULL) { if(searc->vertex【1】==temp)/*find the vertex linked to the signed vertex in the table and update*/ { if((result->cost+linna->value)cost) { searc->cost=result->cost+linna->value;/*set the new value*/ searc->path【0】='v'; searc->path【1】=now->vertex【1】; searc->path【2】='\0'; } break; } else searc=searc->next; } linna=linna->next; } } return 1; } struct Point * FindSmallest(struct Table *head,struct Point *poinhead) { struct Point *result; struct Table *temp; int min=maxium,status=0; head=head->next; poinhead=poinhead->next; while(head!=NULL) { if(!head->Known&&head->cost { min=head->cost; result=poinhead; temp=head; status=1; } head=head->next; poinhead=poinhead->next; } if(status) { temp->Known=1; return result; } else return NULL; } int PrintTable(int start,struct Table *head) { struct Table *begin=head; head=head->next; while(head!=NULL) { if((head->vertex【1】-'0')!=start) PrintPath(start,head,begin); head=head->next; } return OK; } int PrintPath(int start,struct Table *head,struct Table *begin) { struct Table *temp=begin->next,*p,*t; p=head; t=begin; if((p->vertex【1】-'0')!=start&&p!=NULL) { while(temp->vertex【1】!=p->path【1】&&temp!=NULL) temp=temp->next; PrintPath(start,temp,t); printf("%s",p->vertex); } else if(p!=NULL) printf("\n%s",p->vertex); return OK;
编辑本段时间复杂度
我们可以用大O符号将Dijkstra算法的运行时间表示为边数m和顶点数n的函数。 Dijkstra算法最简单的实现方法是用一个链表或者数组来存储所有顶点的集合Q,所以搜索Q中最小元素的运算(Extract-Min(Q))只需要线性搜索Q中的所有元素。这样的话算法的运行时间是O(n2)。 对于边数少于n2稀疏图来说,我们可以用邻接表来更有效的实现Dijkstra算法。同时需要将一个二叉堆或者斐波纳契堆用作优先队列来寻找最小的顶点(Extract-Min)。当用到二叉堆的时候,算法所需的时间为O((m+n)log n),斐波纳契堆能稍微提高一些性能,让算法运行时间达到O(m + n log n)。相关问题和算法 在Dijkstra算

法的基础上作一些改动,可以扩展其功能。例如,有时希望在求得最短路径的基础上再列出一些次短的路径。为此,可先在原图上计算出最短路径,然后从图中删去该路径中的某一条边,在余下的子图中重新计算最短路径。对于原最短路径中的每一条边,均可求得一条删去该边后子图的最短路径,这些路径经排序后即为原图的一系列次短路径。 OSPF(open shortest path first, 开放最短路径优先)算法是Dijkstra算法在网络路由中的一个具体实现。 与Dijkstra算法不同,Bellman-Ford算法可用于具有负花费边的图,只要图中不存在总花费为负值且从源点 s 可达的环路(如果有这样的环路,则最短路径不存在,因为沿环路循环多次即可无限制的降低总花费)。 与最短路径问题有关的一个问题是旅行商问题(traveling salesman problem),它要求找出通过所有顶点恰好一次且最终回到源点的最短路径。该问题是NP难的;换言之,与最短路径问题不同,旅行商问题不太可能具有多项式时间算法。 如果有已知信息可用来估计某一点到目标点的距离,则可改用A*算法,以减小最短路径的搜索范围。

相关文档
最新文档