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. pdm文件打开方式

    转自:https://blog.csdn.net/qq_36855191/article/details/79299216 pdm打开网站:http://www.dmanywhere.cn/

  2. MySql数据库操作之数据约束

    首先数据库的外键是数据库提供的一种完整性约束.在许多数据库的书上也会介绍到,然而对于外键这个完整性性约束究竟应该在数据库端实现,还是在项目业务端实现很多人有着不同的意见. 个人开发(小型应用).数据库 ...

  3. FreeRTOS 任务挂起和恢复

    在使用RTOS的时候一个实时应用可以作为一个独立的任务.每个任务都有自己的运行环境, 不依赖于系统中其他的任务或者RTOS调度器. 任何一个时间点只能有一个任务运行,具体运行哪个任务是由RTOS调度器 ...

  4. 【SpringMVC】请求乱码处理

    一.post请求乱码 二.get请求乱码 一.post请求乱码 在web.xml中加入 <filter> <filter-name>CharacterEncodingFilte ...

  5. py map reduce filter 总结

    array=[1,3,4,71,2] ret=[] for i in array: ret.append(i**2) print(ret) #如果我们有一万个列表,那么你只能把上面的逻辑定义成函数 d ...

  6. mamcached+(magent+keepalived高可用)搭建及理论概述

    目录 一.理论概述 工作流程 二.部署 环境 环境概述 部署 三.测试 四.总结 一.理论概述 Memcached服务器端与PHP-Memcache客户端安装配置_服务器应用_Linux公社-Linu ...

  7. Python_关键字列表

    1.Python关键字列表

  8. JAVA API连接HDFS HA集群

    使用JAVA API连接HDFS时我们需要使用NameNode的地址,开启HA后,两个NameNode可能会主备切换,如果连接的那台主机NameNode挂掉了,连接就会失败. HDFS提供了names ...

  9. centos 下 sphinx安装和配置

    一.安装前提必备先安装工具 yum -y install make gcc g++ gcc-c++ libtool autoconf automake imake mysql-devel libxml ...

  10. vue 对象更改检测注意事项