bon

  C++博客 :: 首页 :: 联系 :: 聚合  :: 管理
  46 Posts :: 0 Stories :: 12 Comments :: 0 Trackbacks

常用链接

留言簿(2)

我参与的团队

搜索

  •  

最新评论

阅读排行榜

评论排行榜

Dijkstra算法,最小优先队列用堆(Heap)实现
伪代码描述
void dijkstra()
{
         Q=V;
         S={};      // 空集
         while(Q!={})
         {
               v = ExtractMin(Q);
               S = S + {v};
               Q = Q - {v};
               for all edge(v,u), relax the edge;         // if(d[v] + dis[v][u] < d[u]) d[u] = d[v] + dis[v][u];
         }
}
  1/*
  2    最基本的二叉堆是实现不了的,因为dijkstra要求在运行过程中随时修改堆内元素,因此要用扩展版的、引入了外部指针的二叉堆 
  3    另外,当图用邻接表来表示的时候,用二叉堆的时间复杂度为O(ElgV),不用二叉堆的复杂的是O(V^2);不用邻接表的时候,用二叉
  4    堆时间复杂度为O(V^2lgV),不用二叉堆的时间复杂度为O(V^2)。也就是说,只有当使用邻接表来表示稀疏图的时候,使用二叉堆才
  5    有效率优势。因此本程序使用邻接表来表示图
  6*/

  7#include <stdio.h>
  8#include <iostream>
  9#define INF 0xfffffff
 10#define MAXN 100
 11
 12using namespace std;
 13
 14int deg[MAXN];                // 节点i的度
 15int list[MAXN][MAXN][2];    // list[i][j][1]:节点i第j个邻接节点在list中的下标,list[i][j][2]表示它们之间的距离
 16int heap[MAXN];                // 堆,heap[i]存储的是节点的编号
 17int key[MAXN];                // 堆中元素的值,算法结束时为各点到源s的最短路的值
 18int pos[MAXN];                // pos[i]表示第i个节点在堆中的位置
 19int count;                    // 未找到最短路径的节点数目,也是堆的大小
 20bool exist[MAXN];            // 标识节点i是否还未找到最短路
 21int n;                        // 结点数
 22int trace[MAXN];            // 存放最短路的路径
 23// 交换两个整数
 24void swap(int &a,int &b)
 25{
 26    int tmp=a;
 27    a=b;
 28    b=tmp;
 29}

 30// 向下调整
 31void siftdown(int index)
 32{
 33    pos[heap[count]]=pos[heap[index]];
 34    heap[index]=heap[count];
 35    int i=index,j;
 36    while(2*i<=count)
 37    {
 38        j=2*i;
 39        if(key[heap[j+1]]<key[heap[j]] && j+1<=count) j++;
 40        if(key[heap[j]]>=key[heap[i]]) break;
 41        swap(pos[heap[i]],pos[heap[j]]);
 42        swap(heap[i],heap[j]);
 43        i=j;
 44    }

 45}

 46// 向上调整
 47void siftup(int index)
 48{
 49    int i=index;
 50    while(i>1 && key[heap[i]]<key[heap[i/2]])
 51    {
 52        swap(pos[heap[i]],pos[heap[i/2]]);
 53        swap(heap[i],heap[i/2]);
 54        i/=2;
 55    }

 56}

 57// 找到当前离source最近的点,返回它的编号
 58int extract()
 59{
 60    int tmp=heap[1];
 61    if(count>1) siftdown(1);
 62    return tmp;
 63}

 64// 修改编号为id的结点在堆中的值,并调整堆
 65void relax(int u)
 66{// 若d[u]+dis[u][v]<d[v],则修改d[v]为d[u]+dis[u][v];u为刚从堆中弹出的点,有向边(u,v)
 67    for(int i=0;i<deg[u];i++)
 68    {
 69        if(exist[list[u][i][0]] == true && key[u]+list[u][i][1]<key[list[u][i][0]])
 70        {
 71            key[list[u][i][0]]=key[u]+list[u][i][1];
 72            trace[list[u][i][0]]=u;
 73            int p=pos[list[u][i][0]];
 74            siftup(p);
 75        }

 76    }

 77}

 78
 79void dijkstra()
 80{
 81    int i,j,k;
 82    for(i=1;i<=n;i++)
 83    {
 84        heap[i]=i;
 85        exist[i]=true;
 86        pos[i]=i;        // 源为1
 87        key[i]=INF;
 88    }

 89    // 初始时堆Q中存放所有的节点
 90    count=n;
 91    key[1]=0;
 92    while(count>0)
 93    {
 94        int id=extract();    // 当前距离节点1最近的点提出来并修改所有与它邻接的点
 95          count--;
 96        exist[id]=false;
 97        relax(id);
 98    }

 99    return;
100}

101
102int main()
103{
104    freopen("test.txt","r",stdin);
105    scanf("%d",&n);
106    count=n;
107    for(int i=1;i<=n;i++)
108    {
109        scanf("%d",&deg[i]);
110        for(int j=0;j<deg[i];j++)
111        {
112            scanf("%d%d",&list[i][j][0],&list[i][j][1]);
113        }

114    }

115    dijkstra();
116    for(i=1;i<=n;i++) printf("node %d precessor %d length %d\n",i,trace[i],key[i]);
117    return 1;
118}
posted on 2008-01-19 21:32 bon 阅读(203) 评论(0)  编辑 收藏 引用

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


Google PageRank 
Checker - Page Rank Calculator