dijkstra算法

来源:互联网 发布:国内域名 国外服务器 编辑:程序博客网 时间:2024/06/10 04:40

/*dijkstra algorithm
author:wuzuquan
last_modify:2008-1-12
*/
#include <stdio.h>
#include <limits.h>
#define MAX_DIST 10000
#define NIL 10000
#define VNUM 5

#define PARENT(i) ((i)>>1)
#define LEFT(i) ((i)<<1)
#define RIGHT(i) ((LEFT(i))+1)

typedef struct
{
 int v;/*顶点u-->v*/
 int w;
}edge;

int parent[VNUM];
int d[VNUM];/*描述从S到V的最短路径上权值的上界---最短路径估计*/

/** 最小优先队列描述**********/
int heap_size=VNUM;

void swap(int *x, int *y)
{
    int temp;
    temp = *x;
 *x = *y;
 *y = temp;
}

void min_heaplfy(int *a,int i)
{//使以i为根的子树成为最小堆
 int left=LEFT(i);
 int right=RIGHT(i);
 int smallest=0;
 if (left<=heap_size && d[a[left]] < d[a[i]])
  smallest=left;
 else
  smallest=i;
 if (right<=heap_size && d[a[right]] < d[a[smallest]])
  smallest=right;//select a smallest element
 if (smallest!=i)
 {
  swap(&a[i],&a[smallest]);
  min_heaplfy(a,smallest);
 }
}

void build_min_heap(int *a)
{//对每一个非叶子结点都调用一次min_heaplfy
 int i=0;
 for (i=heap_size/2;i>=1;i--)
 {
  min_heaplfy(a,i);
 }
}

int heap_extract_min(int *a)
{//去掉并返回A中具有最小关键字的元素
 int min=0;
 if (heap_size<1)
  printf("heap underflow!/n");
    min=a[1];
 a[1]= a[heap_size];
 heap_size-=1;
 min_heaplfy(a,1);
 return min;
}

/************************************************************************/
void initialize_single_source(edge *list, int *head, int s)
{/*对最短路径估计和前趋进行初始化*/
 int v=0;
 for (; v<VNUM; v++)
 {
  d[v]=MAX_DIST;
  parent[v]=NIL;
 }
 d[s]=0;
}

void relax(int u, int v, int w)
{//测试是否可以通过U,对迄今找到的到V的最短路径进行改进
 if (d[v] > (d[u]+w))
 {
  d[v] = d[u]+w;
  parent[v] =u;
 }
}

void printpath(int source,int dest)
{
 int path[VNUM],i=0;
 if (parent[dest]==NIL)
 {
  printf("no path from %d to %d exists!",source,dest);
 }
 while (dest!=NIL)
 {
  path[i]=dest;//记录路径中的顶点
  dest=parent[dest];
  i++;
 }
 for (i=i-1; i>=1; i--)
 {
  printf(" %d-->",path[i]);
 }
 printf("%d:",path[i]);
}

void print_all_path(int source)
{//打印出所有的从source到其他顶点的最短路径
 int i=0;
 printf("the minimum paths figured out by dijkstra algorithm are follows:/n");
 for (i=1; i<VNUM; i++)
 {
  printpath(source,i);
  printf(" %d/n",d[i]);
 }
}

void dijkstra(edge *list,int *head, int s)
{
 int Q[VNUM+1]={0,0,1,2,3,4};//下标为0的元素不使用,后面的元素表示每个顶点
 initialize_single_source(list,head,s);//initialize
 build_min_heap(Q);//建立一个最小堆,key为d[Q[i]]

 while (heap_size>0)
 {//heap_size表示Q中有效元素的个数,Q[0]不予使用
  int i,current;
  current=heap_extract_min(Q);//将关键字最小的顶点出列
  for (i=head[current]; i<head[current+1]; i++)
  {//对current关联的每个顶点进行松弛处理
   relax(current,list[i].v,list[i].w);
  }
  build_min_heap(Q);//rebuild minimum heap by the key "d"
 }
}

int main()
{
 edge list[11]={ {1,10},{3,5},
     {2,1},{3,2},
     {4,4},
     {1,3},{2,9},{4,2},
     {0,7},{2,6}};
 int head[VNUM+1]={0,2,4,5,8,10};
 dijkstra(list,head,0);
 
 print_all_path(0);
    return 0;

原创粉丝点击