Radix Heap ---Dijkstra算法的优化 BY Gremount
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的更多相关文章
- 最短路模板(Dijkstra & Dijkstra算法+堆优化 & bellman_ford & 单源最短路SPFA)
关于几个的区别和联系:http://www.cnblogs.com/zswbky/p/5432353.html d.每组的第一行是三个整数T,S和D,表示有T条路,和草儿家相邻的城市的有S个(草儿家到 ...
- Dijkstra算法堆优化
转自 https://blog.csdn.net/qq_41754350/article/details/83210517 再求单源最短路径时,算法有优劣之分,个人认为在时间方面 朴素dijkstra ...
- 最短路径-迪杰斯特拉(dijkstra)算法及优化详解
简介: dijkstra算法解决图论中源点到任意一点的最短路径. 算法思想: 算法特点: dijkstra算法解决赋权有向图或者无向图的单源最短路径问题,算法最终得到一个最短路径树.该算法常用于路由算 ...
- POJ 3268 Silver Cow Party 最短路—dijkstra算法的优化。
POJ 3268 Silver Cow Party Description One cow from each of N farms (1 ≤ N ≤ 1000) conveniently numbe ...
- Dijkstra算法堆优化详解
DIJ算法的堆优化 DIJ算法的时间复杂度是\(O(n^2)\)的,在一些题目中,这个复杂度显然不满足要求.所以我们需要继续探讨DIJ算法的优化方式. 堆优化的原理 堆优化,顾名思义,就是用堆进行优化 ...
- Codeforces 843D (Dijkstra算法的优化,动态最短路)
题面 (http://codeforces.com/problemset/problem/843/D) 题目大意: 给定一张带权无向图,有q次操作 操作有两种 1 v 询问1到v的最短路 2 c 将边 ...
- 最短路-朴素版Dijkstra算法&堆优化版的Dijkstra
朴素版Dijkstra 目标 找到从一个点到其他点的最短距离 思路 ①初始化距离dist数组,将起点dist距离设为0,其他点的距离设为无穷(就是很大的值) ②for循环遍历n次,每层循环里找出不在S ...
- 单源最短路径问题(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 ...
- Dijkstra算法堆优化(vector建图)
#include<iostream> #include<algorithm> #include<string.h> #include<stdio.h> ...
随机推荐
- Topics in CS(difference between compile and interpret)
编译 Compile:把整个程序源代码翻译成另外一种代码,然后等待被执行,发生在运行之前,产物是「另一份代码」. 解释 Interpret:把程序源代码一行一行的读懂然后执行,发生在运行时,产物是「运 ...
- shell 变量的高级用法
变量删除和替换 案例:从头开始匹配,将符合最短的数据删除 (#) variable_1="I love you, Do you love me" echo $variable_1 ...
- CentOS7安装CDH 第十章:CDH中安装Spark2
相关文章链接 CentOS7安装CDH 第一章:CentOS7系统安装 CentOS7安装CDH 第二章:CentOS7各个软件安装和启动 CentOS7安装CDH 第三章:CDH中的问题和解决方法 ...
- c# 属性说明
- request-html模块 (上)
requests-html模块 官方网站 Github网址 请求数据 from requests_html import HTMLSession session = HTMLSession() req ...
- microsoft office 2007 在已经安装pdf maker的情况下另存为没有adobe pdf选项
通常,此类情况是pdf maker 插件被禁用导致,点击office 2007左上角菜单栏,选项,加载项,在管理处选择禁用项目, 找到acrobat pdf maker office com addi ...
- jade注释
在jade里面注释是有多种方式的 单行注释,加两个//,跟js里面一样 //h1.title#title imoock jade study => <!--h1.title#title i ...
- opencv 图片识别
# -*- coding: utf-8 -*-"""Created on Fri Nov 22 21:35:12 2019 @author: Administrator& ...
- element-ui upload组件 onchange事件 传自定义参数
<el-upload class="upload-demo" list-type="picture" accept=" ...
- Robot Framework--接口测试中常见的四种POST方式
写接口测试用例时,遇到以json格式提交数据时,报错,Request如下图: Response如下图: 改成form格式提交,可以正常运行,如下图: 代码如下: ------------------- ...