1,用set模拟优先级队列:
需要注意的是:在编写Node的“<”比较函数时,必须保证它是“严格弱小于”的,因为对set进行操作的函数如insert,find,erase等都是通过这个函数进行比较的,如果对两个键值都不能 判断它们的“<”关系,则认为它们相等。
view plaincopy to clipboardprint?
#include <iostream>
#include <set>
using namespace std;
const int N = 5;
const int E = 7;
const int MAX=65536;
int g[N][N];
int dis[N];
int pre[N];
struct Node
{
int id;
int len;
bool operator<(const Node &n)const//保证比较函数的严格若排序(如果两个键值,它们之间都不存在“小于关系”,则被视为相等)
{
if(len == n.len)
return id<n.id;
else
return len<n.len;
}
};
struct cmp
{
bool operator()(const Node &n1,const Node &n2)const
{
return n1<n2;
}
};
set<Node> mq;//模拟优先级队列(len越小优先级越大)
void branch_remove(int s)
{
dis[s]=0;
pre[s]=-1;
Node e;
e.id = s;
e.len = 0;
mq.insert(e);
int j = 0;
while(!mq.empty())
{
Node p = *(mq.begin());//取出最小值(优先级最高)
for(j=0;j<N;j++)
{
if(g[p.id][j]!=MAX && g[p.id][j]+p.len<dis[j])
{
dis[j] = g[p.id][j]+dis[p.id];
pre[j] = p.id;
Node t;
t.id = j;
t.len = dis[j];
//如果当前扩展点已经在队列里,修改其优先级,否则插入该扩展节点
mq.erase(t);
mq.insert(t);
}
}
//移除当前优先级最高的节点(作为活结点已经扩展完毕)
mq.erase(p);
}
}
int main()
{
int i=0;
int j =0;
int c=1;
for(i=0;i<N;i++)
for(j=0;j<N;j++)
if(i==j)
g[i][j] = 0;
else
g[i][j] = MAX;
for(i=0;i<N;i++)
dis[i]=MAX;
while(c<=E)
{
cin>>i;
cin>>j;
cin>>g[i][j];
c++;
}
branch_remove(0);
for(i=0;i<N;i++)
cout << dis[i]<<" ";
cout << endl;
}
#include <iostream>
#include <set>
using namespace std;
const int N = 5;
const int E = 7;
const int MAX=65536;
int g[N][N];
int dis[N];
int pre[N];
struct Node
{
int id;
int len;
bool operator<(const Node &n)const//保证比较函数的严格若排序(如果两个键值,它们之间都不存在“小于关系”,则被视为相等)
{
if(len == n.len)
return id<n.id;
else
return len<n.len;
}
};
struct cmp
{
bool operator()(const Node &n1,const Node &n2)const
{
return n1<n2;
}
};
set<Node> mq;//模拟优先级队列(len越小优先级越大)
void branch_remove(int s)
{
dis[s]=0;
pre[s]=-1;
Node e;
e.id = s;
e.len = 0;
mq.insert(e);
int j = 0;
while(!mq.empty())
{
Node p = *(mq.begin());//取出最小值(优先级最高)
for(j=0;j<N;j++)
{
if(g[p.id][j]!=MAX && g[p.id][j]+p.len<dis[j])
{
dis[j] = g[p.id][j]+dis[p.id];
pre[j] = p.id;
Node t;
t.id = j;
t.len = dis[j];
//如果当前扩展点已经在队列里,修改其优先级,否则插入该扩展节点
mq.erase(t);
mq.insert(t);
}
}
//移除当前优先级最高的节点(作为活结点已经扩展完毕)
mq.erase(p);
}
}
int main()
{
int i=0;
int j =0;
int c=1;
for(i=0;i<N;i++)
for(j=0;j<N;j++)
if(i==j)
g[i][j] = 0;
else
g[i][j] = MAX;
for(i=0;i<N;i++)
dis[i]=MAX;
while(c<=E)
{
cin>>i;
cin>>j;
cin>>g[i][j];
c++;
}
branch_remove(0);
for(i=0;i<N;i++)
cout << dis[i]<<" ";
cout << endl;
}
2,使用priority_queue
view plaincopy to clipboardprint?
#include <iostream>
#include <queue>
#include <functional>
using namespace std;
const int N = 5;
const int E = 7;
const int MAX=65536;
int g[N][N];
int dis[N];
int pre[N];
struct Node
{
int id;
int len;
bool operator<(const Node &n)const//保证比较函数的严格若排序(如果两个键值,它们之间都不存在“小于关系”,则被视为相等)
{
if(len == n.len)
return id<n.id;
else
return len<n.len;
}
};
struct cmp
{
bool operator()(const Node &n1,const Node &n2)const
{
return n1<n2;
}
};
priority_queue<Node,vector<Node>,cmp >mq;
void branch_remove(int s)
{
dis[s]=0;
pre[s]=-1;
Node e;
e.id = s;
e.len = dis[s];
mq.push(e);
int j = 0;
while(!mq.empty())
{
Node t = mq.top();
for(j=0;j<N;j++)
{
if(g[t.id][j]!=MAX && g[t.id][j]+t.len < dis[j])
{
dis[j] = g[t.id][j]+t.len;
pre[j] = t.id;
Node p;
p.id = j;
p.len = dis[j];
mq.push(p);
}
}
mq.pop();
}
}
int main()
{
int i=0;
int j =0;
int c=1;
for(i=0;i<N;i++)
for(j=0;j<N;j++)
if(i==j)
g[i][j] = 0;
else
g[i][j] = MAX;
for(i=0;i<N;i++)
dis[i]=MAX;
while(c<=E)
{
cin>>i;
cin>>j;
cin>>g[i][j];
c++;
}
branch_remove(0);
for(i=0;i<N;i++)
cout << dis[i]<<" ";
cout << endl;
}
#include <iostream>
#include <queue>
#include <functional>
using namespace std;
const int N = 5;
const int E = 7;
const int MAX=65536;
int g[N][N];
int dis[N];
int pre[N];
struct Node
{
int id;
int len;
bool operator<(const Node &n)const//保证比较函数的严格若排序(如果两个键值,它们之间都不存在“小于关系”,则被视为相等)
{
if(len == n.len)
return id<n.id;
else
return len<n.len;
}
};
struct cmp
{
bool operator()(const Node &n1,const Node &n2)const
{
return n1<n2;
}
};
priority_queue<Node,vector<Node>,cmp >mq;
void branch_remove(int s)
{
dis[s]=0;
pre[s]=-1;
Node e;
e.id = s;
e.len = dis[s];
mq.push(e);
int j = 0;
while(!mq.empty())
{
Node t = mq.top();
for(j=0;j<N;j++)
{
if(g[t.id][j]!=MAX && g[t.id][j]+t.len < dis[j])
{
dis[j] = g[t.id][j]+t.len;
pre[j] = t.id;
Node p;
p.id = j;
p.len = dis[j];
mq.push(p);
}
}
mq.pop();
}
}
int main()
{
int i=0;
int j =0;
int c=1;
for(i=0;i<N;i++)
for(j=0;j<N;j++)
if(i==j)
g[i][j] = 0;
else
g[i][j] = MAX;
for(i=0;i<N;i++)
dis[i]=MAX;
while(c<=E)
{
cin>>i;
cin>>j;
cin>>g[i][j];
c++;
}
branch_remove(0);
for(i=0;i<N;i++)
cout << dis[i]<<" ";
cout << endl;
}
二者的实现不同之处是:
使用set时,由于set能保证键值的唯一,所以在进行节点的扩展时,实际上是替换set中已存在节点的len值或者添加新节点。
而使用priority_queue不能保证键值唯一,且又不方便查找已存在节点(没有迭代器适配器等操作),故在进行节点扩展时,队列中可能存在重复键值节点,单它们的len值不同,这并不影响对本问题的求解,因为可以通过约束函数将len值较大的节点进行剪枝,但是在运用priority_queue求解其它问题时,这是应当注意的。
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/clearriver/archive/2009/08/30/4499739.aspx
分享到:
相关推荐
1.分支限界法求解单源最短路径 2.C++源码+程序说明文档 3.源码带详细注释
有很长时间没有上传了,主要是因为这些天出了些小事。这个是用分支限界法求解单源最短路径问题的算法。
(1)描述:采用广度优先产生状态空间树的结点,并使用剪枝函数的方法称为分枝限界法。 所谓“分支”是采用广度优先的策略,依次生成扩展结点的所有分支(即:儿子结点)。 所谓“限界”是在结点扩展过程中,计算...
单源最短路径--分支限界法
单源最短路径C语言实现,简单易懂,适合算法学习
应用分枝限界法的算法设计思想求解单源最短路径问题。 【实验性质】 在完成的过程中注意与回溯算法思想的比较,重点注意两种算法思想各自的特点以及实现方式比较。此实验的性质为综合性实验 【实验内容与要求】 采用...
单源最短路径的分支限界算法_文档.doc
用python实现迪杰斯特拉算法,单源最短路径,有向图权值无负值,用邻接矩阵来存储有向图,实现路径存储和路径打印
采用广度优先产生状态空间树的结点,并使用剪枝函数的方法称为分枝限界法。在下图所给的有向图G中,每一边都有一个非负边权。要求图G的从源顶点s到目标顶点t之间的最短路径。
算法课程设计报告,单元最短路径问题。单源最短路劲问题适合于用分支限界法求解。在图中所给的有向图G中,...解单源最短路径问题的优先队列式分支限界法用一极小堆来存储活结点表,其优先级是结点所对应的的当前路长。
实验五:分枝限界法_最短路径问题.pdf
实验四单源最短路径(分支限界法).pdf
Dijketra算法求解单源最短路径问题,完全手写。有大量注释,便于阅读。
贪新算法和分支限界法解单源最短路径.doc
实验五:分枝限界法_最短路径问题.doc
分支限界算法之0-1背包问题和单源最短路径问题java源程序参考.pdf
1、理解分支限界法的剪枝搜索策略; 2、掌握分支限界法的算法框架; 3、通过应用范例学习分支限界法的设计策略。 二、实验环境 1、硬件环境:Windows 10 2、软件环境: 编译器:Dev C++ 语言:C语言
分支界限法求单元点最短路径 代码 实验报告
附送Kruskal最小生成树算法,都是本人的劳动成果,包含输入输出的完整控制台程序,希望大家下完顶一下:)
本程序对有路径长度和路径花费的有向图,采用分枝限界+DFS的技术得出最短路径的最优解,采用C++语言。 代码注意丰富。压缩包内含问题描述背景、数据、程序说明文档、可执行程序、源码