Radix Heap 算法是在Dijkstra的Dial实现的基础上,通过减少对桶的使用,来优化算法的时间复杂度:

Dial 时间复杂度是O(m+nC)     -------C是最长的链路

Radix Heap 时间复杂度是O(m+n*log(nC))

本质上来说Radix Heap是Dial和Dijkstra的折中,因为Dial用NC个桶,Dijkstra用1个桶

下面是本程序中使用的一些函数介绍:

void radix_heap():

(1)对所有桶的range初始化

(2)所有节点的初始化(这一步可以在建图的时候完成);

(2)除开始点,其他全部放入无穷桶里,注意这里的无穷桶的id=初始d值对2求对数后上去整;

(3)更新源节点

(4)后续是找最小值和更新的操作循环(类似于dijkstra算法)





int FindMin():

(1)移动指针到第一个不为空的桶

(2)如果桶的编号是0或者1,则任取元素出来返回;

     如果编号大于1且桶内元素个数为1,则将该元素取出来返回;

     如果编号大于1且桶内的元素个数大于1,则先找出最小值,再执行redistribute()

 重置桶里的元素





int Redistribute():

(1)根据最小值,更改桶的range,修改range和桶的映射;

(2)将该桶内的元素重置位置,返回最小值;





void Update(int i):

根据i点的d值和邻接边的值来更改与i相连的其他节点的d值;

下面是我写的程序,分为三部分,第一部分是主程序,第二部分是资源程序,第三部分是头文件

第一部分:创建如下图:

//radix_heap.cpp 主程序:完成图的创建和最短路函数调用
#include "resources.h" CEdge::CEdge(int a, int b, int c, int d){
tail=a;
head=b;
weight=c;
capacity=d;
} CEdge::CEdge(int a, int b, int c){
head=b;
tail=a;
weight=c;
} CEdge::CEdge(CEdge & x){
tail=x.getTail();
head=x.getHead();
weight=x.getWeight();
capacity=x.getCap();
} CGraph::CGraph(list<CEdge*> listEdge){
IncidentList=listEdge;
numVertex=N;
numEdge=listEdge.size();
} int main()
{
list<CEdge*> listEdge; CEdge* e1=new CEdge(1,2,1,10);
CEdge* e2=new CEdge(2,1,1,10);
CEdge* e3=new CEdge(1,7,1,10);
CEdge* e4=new CEdge(7,1,1,10);
CEdge* e5=new CEdge(7,10,1,10);
CEdge* e6=new CEdge(10,7,1,10);
CEdge* e7=new CEdge(3,2,1,10);
CEdge* e8=new CEdge(2,3,1,10);
CEdge* e9=new CEdge(3,4,1,10);
CEdge* e10=new CEdge(4,3,1,10);
CEdge* e11=new CEdge(4,10,1,10);
CEdge* e12=new CEdge(10,4,1,10);
CEdge* e13=new CEdge(1,5,1,10);
CEdge* e14=new CEdge(5,1,1,10);
CEdge* e15=new CEdge(6,5,1,10);
CEdge* e16=new CEdge(5,6,1,10);
CEdge* e17=new CEdge(6,10,1,10);
CEdge* e18=new CEdge(10,6,1,10);
CEdge* e19=new CEdge(8,10,1,10);
CEdge* e20=new CEdge(10,8,1,10);
CEdge* e21=new CEdge(9,10,1,10);
CEdge* e22=new CEdge(10,9,1,10);
listEdge.push_back(e1);
listEdge.push_back(e2);
listEdge.push_back(e3);
listEdge.push_back(e4);
listEdge.push_back(e5);
listEdge.push_back(e6);
listEdge.push_back(e7);
listEdge.push_back(e8);
listEdge.push_back(e9);
listEdge.push_back(e10);
listEdge.push_back(e11);
listEdge.push_back(e12);
listEdge.push_back(e13);
listEdge.push_back(e14);
listEdge.push_back(e15);
listEdge.push_back(e16);
listEdge.push_back(e17);
listEdge.push_back(e18);
listEdge.push_back(e19);
listEdge.push_back(e20);
listEdge.push_back(e21);
listEdge.push_back(e22);
CGraph g(listEdge);
g.p1();
g.p2();
g.p3();
g.p4();
g.radix_heap(g,1);
getchar();
return 0;
}

第二部分:

//resources.h 所用的类:点,边,图
//图中包含对图的测量函数(p1`、p2、p3、p4)
//radix_heap() FindMin() Update() Redistribute()
#include "common.h" class CVertex{
public:
int d;
int p;
int ID;
CVertex(int x){ID=x;d=INF;p=NULL;}
~CVertex(){;}
}; class CEdge{
private:
int tail, head;
int weight, capacity;
public:
CEdge(int a, int b, int c, int d);
CEdge(int a, int b, int c);
CEdge(CEdge &x);
int getHead(){return head;}
int getTail(){return tail;}
int getWeight(){return weight;}
int getCap(){return capacity;}
bool operator<(CEdge& x){
if(weight<x.weight)
return 1;
else
return 0;
}
}; class CGraph{
private:
int numVertex;
int numEdge;
list<CEdge*> IncidentList;
public:
set<int> S;
set<int> V;
int d[N+10];
int p[N+10]; map<int,int> degree_vertex;
multimap<int,int> degree_vertex2; map<int,list<int>> adjlist; vector<vector<CEdge*>> adjmatrix; map<int,list<CEdge*>> nelist; map<int,map<int, CVertex*>> mapBuckets;
map<int, CVertex*> mapVID_Vertex; map<int,map<int, CVertex*>>::iterator itBucket;
map<int, CVertex*>::iterator itcv;
int range[2024];
int rbegin[20];
int rend[20];
int zhishu;
int db[20];
CGraph(char* inputFile);
CGraph(list<CEdge*> listEdge);
CGraph(CGraph &);
void init()
{
//range表初始化
zhishu=2;
rbegin[0]=1;
rend[0]=1;
rbegin[1]=2;
rend[1]=2;
for(int i=2;i<=10;i++)
{
zhishu=zhishu*2;
rbegin[i]=rend[i-1]+1;
rend[i]=zhishu;
} //等比数列初始化
db[1]=1;
for(int i=2;i<=10;i++)
db[i]=db[i-1]*2;
}
int getNumVertex(){
return numVertex;
}
int getNumEdge(){
return numEdge;
}
int cmp(const pair<int,int> &x, const pair<int, int> &y){
return x.second > y.second;
}
void p1(){
list<CEdge*>::iterator it,iend;
multimap<int,int>::iterator it2;
iend=IncidentList.end();
vector<pair<int,int>> dv_vec;
for(int i=1;i<=N;i++)
degree_vertex[i]=0;
for(it=IncidentList.begin();it!=iend;it++)
degree_vertex[(*it)->getTail()]++;
for(int i=1;i<=N;i++)
degree_vertex2.insert(pair<int,int>(degree_vertex[i],i));
it2=--degree_vertex2.end();
printf("project 1:\n");
for(;it2!=degree_vertex2.begin();it2--)
printf("%d,%d\n",it2->second,it2->first);
} void p2(){
list<CEdge*>::iterator it,iend;
list<int>::iterator it2,iend2;
iend=IncidentList.end();
//printf("incidentList:\n");
for(it=IncidentList.begin();it!=iend;it++){
adjlist[(*it)->getTail()].push_back((*it)->getHead());
//printf("%d,%d\n",(*it)->getTail(),(*it)->getHead());
}
it2=adjlist[3].begin();
iend2=adjlist[3].end();
printf("\n");
printf("project 2:\n");
printf("3:");
for(;it2!=iend2;it2++)
printf("%d ",*it2);
} void p3(){
list<CEdge*>::iterator it,iend;
iend=IncidentList.end();
CEdge* emptyedge=new CEdge(-1,-1,-1,-1);
for(int i=0;i<=numVertex;i++)
{
vector<CEdge*> vec;
for(int j=0;j<=numVertex;j++)
{
vec.push_back(emptyedge);
}
adjmatrix.push_back(vec);
}
for(it=IncidentList.begin();it!=iend;it++){
//CEdge* e = new CEdge((*it)->getTail(),(*it)->getHead(),(*it)->getWeight(),(*it)->getCap());
adjmatrix[(*it)->getTail()][(*it)->getHead()] = *it ;
}
printf("\n");
printf("project 3:\n");
printf("%d,%d",adjmatrix[2][3]->getTail(),adjmatrix[2][3]->getHead());
} void p4(){
list<CEdge*>::iterator it,iend; iend=IncidentList.end();
for(it=IncidentList.begin();it!=iend;it++){
nelist[(*it)->getTail()].push_back(*it);
}
printf("\n");
printf("project 4:\n");
list<CEdge*>::iterator it2,iend2;
iend2=nelist[3].end();
for(it2=nelist[3].begin();it2!=iend2;it2++)
printf("%d %d\n",(*it2)->getTail(),(*it2)->getHead());
} void Update(int i){
list<CEdge*>::iterator it,iend;
it=nelist[i].begin();
iend=nelist[i].end();
for(;it!=iend;it++)
if((*it)->getWeight()+mapVID_Vertex[i]->d < mapVID_Vertex[(*it)->getHead()]->d){
int d;
d=(*it)->getWeight()+mapVID_Vertex[i]->d;
//增加新的点,删除旧的点,改动点信息
int k;
k = mapVID_Vertex[(*it)->getHead()]->d;
//pair<int,CVertex*> p((*it)->getHead(),mapBuckets[int(ceil((log((float)k))/(log((float)2))))][(*it)->getHead()]);
pair<int,CVertex*> p((*it)->getHead(),mapVID_Vertex[(*it)->getHead()]);
mapBuckets[int(ceil((log((float)d))/(log((float)2))))].insert(p);
mapBuckets[int(ceil((log((float)k))/(log((float)2))))].erase((*it)->getHead());
mapVID_Vertex[(*it)->getHead()]->d = (*it)->getWeight()+mapVID_Vertex[i]->d;
mapVID_Vertex[(*it)->getHead()]->p = i;
}
//printf("update\n");
} int Redistribute(int dmin, int mini)
{
rbegin[0]=dmin;
rend[0]=dmin;
rbegin[1]=dmin+1;
rend[1]=dmin+1;
range[dmin]=0;
range[dmin+1]=1;
for(int i=2;i<=10;i++)
{
rbegin[i]=rend[i-1]+1;
rend[i]=rend[i-1]+db[i];
for(int j=rbegin[i];j<=rend[i];j++)
range[j]=i;
}
cout<<"middle"<<endl;
//重置该桶内的所有节点
itcv=itBucket->second.begin();
for(;itcv!=itBucket->second.end();)
{
//增加新的点,删除旧的点
cout<<"middle2"<<endl;
pair<int,CVertex*> p(itcv->first,itcv->second);
//mapBuckets[range[mapVID_Vertex[itcv->first]->d]].insert(p);
mapBuckets[range[itcv->second->d]].insert(p);
cout<<"middle3"<<endl;
mapBuckets[itBucket->first].erase(itcv++);
cout<<"middle4"<<endl;
}
itBucket=mapBuckets.begin();
cout<<"Before_FindMin"<<endl;
int reward;
reward=FindMin();
return reward;
} int FindMin(){
set<int>::iterator vi,vend; //移动指针到第一个不为空的桶
while(1)
{
if(itBucket->second.empty()==true)
itBucket++;
else
{itcv=itBucket->second.begin();break;}
}
if(itBucket->first==0 || itBucket->first==1)
{
int mini;
printf("1 if\n");
mini=itcv->first;
mapBuckets[itBucket->first].erase(itcv++);
printf("min is %d\n",mini);
return mini;
}
else if(itBucket->second.size()==1)
{
int mini;
printf("2 if\n");
mini=itcv->first;
mapBuckets[itBucket->first].erase(itcv++);
//printf("min is %d\n",mini);
return mini;
}
else
{
int dmin=10000;
int mini;
printf("3 if\n");
itcv=itBucket->second.begin();
cout<<mapVID_Vertex[itcv->first]->d<<endl;
for(;itcv!=itBucket->second.end();itcv++)
{
if(mapVID_Vertex[itcv->first]->d < dmin)
{dmin=mapVID_Vertex[itcv->first]->d;mini=itcv->first;}
}
cout<<dmin<<mini<<endl;
itcv=itBucket->second.begin();
return Redistribute(dmin,mini);
} } void radix_heap(CGraph &g,int s){
int i,j;
init();
for(i=1;i<=10;i++)
V.insert(i);
for(i=1;i<=N;i++)//所有节点的初始化
{
CVertex* vertex=new CVertex(i);
pair<int, CVertex*> p(i,vertex);
mapVID_Vertex.insert(p);
} for(i=2;i<=N;i++)//除开始点,其他全部放入无穷桶里
{
pair<int,CVertex*> p2(i,mapVID_Vertex[i]);
mapBuckets[ceil(log(float(INF))/log(2.0))].insert(p2);//10=log1024,对应无穷桶,方便在删除时操作
}
S.insert(s);
V.erase(s);
mapVID_Vertex[1]->d=0;
Update(s);
itBucket=mapBuckets.begin();
while (V.size()!=0)
{
j=FindMin();
S.insert(j);
V.erase(j);
cout<<"V :"<<j<<" "<<V.size()<<endl;
Update(j);
}
printf("\n 1->9:%d\n",mapVID_Vertex[9]->d);
}
};

第三部分:

//一些需要用到的头文件
#ifndef _COMMON_H_
#define _COMMON_H_
#include <map>
#include <vector>
#include <list>
#include <set>
#include <math.h>
using namespace std;
#include <iostream>
#include <stdio.h>
#include <algorithm>
#define INF 1024
#define N 10
#define C 1
#endif

Radix Heap ---Dijkstra算法的优化 BY Gremount的更多相关文章

  1. 最短路模板(Dijkstra & Dijkstra算法+堆优化 & bellman_ford & 单源最短路SPFA)

    关于几个的区别和联系:http://www.cnblogs.com/zswbky/p/5432353.html d.每组的第一行是三个整数T,S和D,表示有T条路,和草儿家相邻的城市的有S个(草儿家到 ...

  2. Dijkstra算法堆优化

    转自 https://blog.csdn.net/qq_41754350/article/details/83210517 再求单源最短路径时,算法有优劣之分,个人认为在时间方面 朴素dijkstra ...

  3. 最短路径-迪杰斯特拉(dijkstra)算法及优化详解

    简介: dijkstra算法解决图论中源点到任意一点的最短路径. 算法思想: 算法特点: dijkstra算法解决赋权有向图或者无向图的单源最短路径问题,算法最终得到一个最短路径树.该算法常用于路由算 ...

  4. POJ 3268 Silver Cow Party 最短路—dijkstra算法的优化。

    POJ 3268 Silver Cow Party Description One cow from each of N farms (1 ≤ N ≤ 1000) conveniently numbe ...

  5. Dijkstra算法堆优化详解

    DIJ算法的堆优化 DIJ算法的时间复杂度是\(O(n^2)\)的,在一些题目中,这个复杂度显然不满足要求.所以我们需要继续探讨DIJ算法的优化方式. 堆优化的原理 堆优化,顾名思义,就是用堆进行优化 ...

  6. Codeforces 843D (Dijkstra算法的优化,动态最短路)

    题面 (http://codeforces.com/problemset/problem/843/D) 题目大意: 给定一张带权无向图,有q次操作 操作有两种 1 v 询问1到v的最短路 2 c 将边 ...

  7. 最短路-朴素版Dijkstra算法&堆优化版的Dijkstra

    朴素版Dijkstra 目标 找到从一个点到其他点的最短距离 思路 ①初始化距离dist数组,将起点dist距离设为0,其他点的距离设为无穷(就是很大的值) ②for循环遍历n次,每层循环里找出不在S ...

  8. 单源最短路径问题(dijkstra算法 及其 优化算法(优先队列实现))

    #define _CRT_SECURE_NO_WARNINGS /* 7 10 0 1 5 0 2 2 1 2 4 1 3 2 2 3 6 2 4 10 3 5 1 4 5 3 4 6 5 5 6 9 ...

  9. Dijkstra算法堆优化(vector建图)

    #include<iostream> #include<algorithm> #include<string.h> #include<stdio.h> ...

随机推荐

  1. nginx 反向代理配置(一)

    文章参考:https://blog.csdn.net/physicsdandan/article/details/45667357       什么是代理?       代理在普通生活中的意义就是本来 ...

  2. js钩子函数实现一个简单动画

    <!DOCTYPE html> <html> <head> <title></title> <meta charset="u ...

  3. Vue注意事项

    在使用Vue中的函数或自己定义的函数或指令的时候,Vue说明如下 在一些自己定义或系统定义的驼峰命名规则的时候,你需要到元素区域引用的使用中间的大写要改成小写在谭家 一条横杠如: 你在var=new ...

  4. Deep Module(深模块)

    Deep Module(深模块) 目录 1,模块化设计 2,接口里有什么 3,抽象 4,深模块 5,浅模块 6,Classitis 7,例子 8,结论 正文 类是不是越小越好?最近在读John Ous ...

  5. SecureCRT进行端口转发

    总共3台机器:my电脑.跳转机器(外网).内网服务器. ​ 首先配置至跳板机(150.236.223.72:22)的连接: ​ 配置完成后选择Connect连接至跳板机,输入密码后可选择“Save p ...

  6. 用来遍历map集合的方法

    map集合是以键值对进行存储值的,所以遍历map集合无非就是获取键和值,根据实际需求,进行获取键和值. 1.无非就是通过map.keySet()获取到值,然后根据键获取到值. for(String s ...

  7. go mod使用

    GO111MODULE 有三个值:off, on和auto(默认值) GO111MODULE=off,go命令行将不会支持module功能,寻找依赖包的方式将会沿用旧版本那种通过vendor目录或者G ...

  8. Visual Studio 快捷键、常见问题

    前言 由于平时自己在使用 VS 过程中遇到过一些很常见的问题,比如基本的设置.工具等.VS 十分的强大(宇宙第一 IDE),所以有些功能藏的深也不好找,就在这里记录下. 正文 一.快捷操作 1.调试. ...

  9. python 'NoneType' object has no attribute 'get'

    获取 页面链接的时候报错 'NoneType' object has no attribute 'get' href = div.find("a").get("href& ...

  10. vscode源码编译疑难问题

    最近把原来老的源码merge到了新的1.15版本源码,以前的依赖问题会导致各种错误,Loading "gc-signals" failed啦,Error: %1 is not a ...