您的位置:首页 > Web前端 > Node.js

Node:最短路径之Dijkstra堆优化

2015-07-16 23:08 681 查看
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <string.h>
#include <stack>
#include <queue>

#define flush(arr,i) memset(arr,i,sizeof(arr))
#define INF 0xfffffff

using namespace std;
const int maxn=1010;
//到节点的距离和第i个节点的前一个节点
int dis[maxn], pre[maxn];
//边集
int cost[maxn][maxn];
//是否在集合之中
bool vis[maxn];

struct Node
{
int nodeId;
int len;
};

Node heap[maxn];

int n, m, s, sz;
/*
测试数据
---------
8 14 6
6 5 1
6 4 3
6 7 6
5 3 3
5 4 1
7 4 1
7 2 4
4 2 9
3 4 1
3 1 4
1 2 1
7 8 14
2 8 2
3 2 2
--------
*/
//数据录入和初始化
void initMap()
{
//没有进入集合
flush(vis, 0);

sz = 0;
scanf("%d%d%d", &n, &m, &s);

int from, to, len;
for(int i = 1; i <= n; i++)
{
dis[i] = INF;
pre[i] = 0;
for(int j = 1; j <= n; j++)
cost[i][j] = INF;
}

for(int i = 0; i < m; i++)
{
scanf("%d%d%d",&from, &to, &len);
printf("%c %c %d\n",from + 'r', to + 'r', len);
cost[from][to] = cost[to][from] = len;

4000
}
}

//路径输出
void showPath(int cur)
{
if(pre[cur])
showPath(pre[cur]);
printf("->%c", cur + 'r');
}

/*
//优化集中在这一部分
int getMinmunNode()
{
int maxCost = INF, pos = -1;
for(int i = 1; i <= n; i++)
if(!vis[i] && dis[i] < maxCost)
{
pos = i;
maxCost = dis[i];
}
//加入集合标记为1
vis[pos] = 1;
return pos;
}
*/
//--------------------------------------------------
//使用堆来进行优化:(用数组进行维护)堆从下标1开始

int getMinmNode()         //最小堆
{
int ret = heap[1].nodeId;
//,第一个节点删除,最后一个放到第一个位置,之后向下调整
heap[1] = heap[sz--];

int cur = 1, son = 2;
//  存在儿子比父亲小
while(son <= sz && (heap[son].len < heap[cur].len || heap[son+1].len < heap[cur].len))
{
if(heap[son].len > heap[son+1].len)
son++;
swap(heap[son].len,heap[cur].len);
swap(heap[son].nodeId,heap[cur].nodeId);
//指针下移
cur = son;
son*= 2;
}
return ret;
}

void deleteNode(int id)
{
int pos = -1;
for(int i = 0; i < sz; i++)
if(heap[i].nodeId == id)
{
pos = i;
break;
}
if(pos != -1)
{
for(int i = pos; i < sz - 1; i++)
heap[i] = heap[i + 1];
sz--;
}
}

void insertNode(Node t)
{
//添加到最后一个节点,向上调整
heap[++sz] = t;
int cur = sz, p = cur/2;
while(p>=1)
{
//比父亲小的节点
if(heap[cur].len < heap[p].len)
{
swap(heap[cur].len,heap[p].len);
swap(heap[cur].nodeId,heap[p].nodeId);
}
cur = p;
p = cur/2;
}
}

//----------------------------------------------------
void Dijkstra(int s)
{
dis[s] = 0;
Node from;
from.len = 0;
from.nodeId = s;

insertNode(from);
//一共更新n次
while(sz)
{
//获取当前的is最小节点进行下一步更新
int cur = getMinmNode();
//输出当前选出的节点
printf("cur %c\n", cur + 'r');
for(int j = 0; j <= n; j++)
//满足更新条件
if(dis[j] > dis[cur] + cost[cur][j])
{
dis[j] = dis[cur] + cost[cur][j];
deleteNode(j);

Node newNode;
newNode.len = dis[j];
newNode.nodeId = j;
insertNode(newNode);

//维护路径
pre[j] = cur;
//输出更新情况
printf("%c->%c:%d ", s + 'r', j + 'r', dis[j]);
}
printf("\n");
}
for(int i = 1; i <= n; i++)
{
showPath(i);
printf(" %d\n",dis[i]);
}
}

int main()
{
freopen("data.txt","r",stdin);
initMap();
Dijkstra(s);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  algorithm dijkstra