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. 【转载】 C#中使用Count方法获取List集合中符合条件的个数

    很多时候操作List集合的过程中,我们需要根据特定的查询条件,获取List集合中有多少个实体对象符合查询条件,例如一批产品的对象List集合,如果这批产品的不合格数量大于10则重点备注.在C#中可以自 ...

  2. ElementUI动态表格数据转换formatter

    elementUI的表格初始化比较简单,声明prop值对应的字段名即可. 而在实际应用中,我们常常有这种需求:从服务器获取的数据并不是我们要显示的最终结果,涉及一些状态.类型.日期时间等的转换,这时候 ...

  3. html+css+javascript网页制作技巧总结1

    (一)div.元素居中中显示方法: 1.宽度要有实际值或百分比值 2.margin:0px auto; 文本内容居中显示的方法: 1.text-align:center; 2.line-height: ...

  4. FreeRTOS 中断配置和临界段

    中断屏蔽寄存器 PRIMASK.FAULTMASK和BASEPRI 1.PRIMASK:这是个只有1个位的寄存器.当它置1时, 就关掉所有可屏蔽的异常,只剩下 NMI和硬fault可以响应.它的缺省值 ...

  5. 【JUC】1.线程

    先复习一下线程的东西: Java线程的内存模型 主内存与工作内存 Java内存模型主要定义了程序中各个变量的访问规则 所有的变量都在主内存,Java堆(线程共享) 每条线程都有自己的工作内存,虚拟机栈 ...

  6. 在openwrt 17.01上编译最新nginx 1.14.2的笔记

    openwrt 17.01源码对应的nginx版本是1.10.2,有些新功能没有,所以需要升级到nginx 1.14.2最新的稳定版 https://github.com/macports/macpo ...

  7. 基于beautifulSoup进行电影网站排名的获取与格式化输出

    要求 编写代码完成以下任务: ① 将地址"http://www.cbooo.cn/year?year=2019"源代码使用任意方法保存到指定文件中(文件类型不限). ② 使用文件流 ...

  8. 阿里P7架构师是如何解决跨域问题的!你有遇到吗?

    现在越来越多的项目就算是一个管理后端也偏向于使用前后端分离的部署方式去做,为了顺应时代的潮流,一前后端分离就产生了跨域问题,所以许多同学把跨域和前后端分离项目联系在了一起,其实跨域产生的原因并不是前后 ...

  9. Java反射中Class.forName和classloader的区别

    Java中Class.forName和classloader都可以用来对类进行加载. Class.forName除了将类的.class文件加载到jvm中之外,还会对类进行解释,执行类中的static块 ...

  10. P2746 P2812 [USACO5.3]校园网Network of Schools[SCC缩点]

    题目描述 一些学校连入一个电脑网络.那些学校已订立了协议:每个学校都会给其它的一些学校分发软件(称作"接受学校").注意即使 B 在 A 学校的分发列表中, A 也不一定在 B 学 ...