• 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:
    ");
    		for(;it2!=degree_vertex2.begin();it2--)
    			printf("%d,%d
    ",it2->second,it2->first);
    	}
    
    	void p2(){
    		list<CEdge*>::iterator it,iend;
    		list<int>::iterator it2,iend2;
    		iend=IncidentList.end();
    		//printf("incidentList:
    ");
    		for(it=IncidentList.begin();it!=iend;it++){
    			adjlist[(*it)->getTail()].push_back((*it)->getHead());
    			//printf("%d,%d
    ",(*it)->getTail(),(*it)->getHead());
    		}
    		it2=adjlist[3].begin();
    		iend2=adjlist[3].end();
    		printf("
    ");
    		printf("project 2:
    ");
    		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("
    ");
    		printf("project 3:
    ");
    		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("
    ");
    		printf("project 4:
    ");
    		list<CEdge*>::iterator it2,iend2;
    		iend2=nelist[3].end();
    		for(it2=nelist[3].begin();it2!=iend2;it2++)
    			printf("%d %d
    ",(*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
    ");
    	}
    
    	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
    ");
    			mini=itcv->first;
    			mapBuckets[itBucket->first].erase(itcv++);
    			printf("min is %d
    ",mini);
    			return mini;
    		}
    		else if(itBucket->second.size()==1)
    		{
    			int mini;
    			printf("2 if
    ");
    			mini=itcv->first;
    			mapBuckets[itBucket->first].erase(itcv++);
    			//printf("min is %d
    ",mini);
    			return mini;
    		}
    		else
    		{
    			int dmin=10000;
    			int mini;
    			printf("3 if
    ");
    			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("
     1->9:%d
    ",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


  • 相关阅读:
    【shell】日志切割
    【PHP】SVN版本差异导出
    Linux服务器上安装JDK
    Linux 下node环境安装
    CentOS 7.3安装mariadb
    Centos 7.4 自动初始化docker环境,配置docker镜像仓库
    Shell 模板 (Yes or NO)
    Linux修改时间和时区
    lvm方式挂载盘及扩容
    安装ansible
  • 原文地址:https://www.cnblogs.com/gremount/p/5768012.html
Copyright © 2020-2023  润新知