分支限界法实验单源最短路径.docx

上传人:b****5 文档编号:28714495 上传时间:2023-07-19 格式:DOCX 页数:14 大小:178.29KB
下载 相关 举报
分支限界法实验单源最短路径.docx_第1页
第1页 / 共14页
分支限界法实验单源最短路径.docx_第2页
第2页 / 共14页
分支限界法实验单源最短路径.docx_第3页
第3页 / 共14页
分支限界法实验单源最短路径.docx_第4页
第4页 / 共14页
分支限界法实验单源最短路径.docx_第5页
第5页 / 共14页
点击查看更多>>
下载资源
资源描述

分支限界法实验单源最短路径.docx

《分支限界法实验单源最短路径.docx》由会员分享,可在线阅读,更多相关《分支限界法实验单源最短路径.docx(14页珍藏版)》请在冰豆网上搜索。

分支限界法实验单源最短路径.docx

分支限界法实验单源最短路径

算法分析与设计实验报告

第七次实验

姓名

学号

班级

时间

12.26上午

地点

工训楼309

实验名称

分支限界法实验(单源最短路径)

实验目的

1.掌握并运用分支限界法的基本思想

2.运用分支限界法实现单源最短路径问题

实验原理

问题描述:

在下图所给的有向图G中,每一边都有一个非负边权。

要求图G的从源顶点s到目标顶点t之间的最短路径。

基本思想:

下图是用优先队列式分支限界法解有向图G的单源最短路径问题产生的解空间树。

其中,每一个结点旁边的数字表示该结点所对应的当前路长。

为了加速搜索的进程,应采用有效地方式选择活结点进行扩展。

按照优先队列中规定的优先级选取优先级最高的结点成为当前扩展结点。

实验步骤

(1)算法从图G的源顶点s和空优先队列开始。

结点s被扩展后,它的儿子结点被依次插入堆中;

(2)算法每次从堆中取出具有最小当前路长的结点作为当前扩展结点,并依次检查与当前扩展结点相邻的所有顶点;

(3)如果从当前扩展结点i到j有边可达,且从源出发,途经i再到j的所相应路径长度,小于当前最优路径长度,则将该顶点作为活结点插入到活结点优先队列中;

(4)结点扩展过程一直继续到活结点优先队列为空时为止。

关键代码

//单源最短路径问题的优先队列式分支限界法

template

voidGraph:

:

shortest_path(intv)

{

//定义最小堆的容量为1000

MinHeap>H(1000);

//定义源为初始扩展结点

MinHeapNodeE;

//初始化源结点

E.i=v;

E.length=0;

dist[v]=0;

while(true)//搜索问题的解空间

{

for(intj=1;j<=n;j++)

if((c[E.i][j]!

=0)&&(E.length+c[E.i][j]

{

//顶点i到顶点j可达,且满足控制约束

//顶点i和j之间有边,且此路径小于原先从源点到j的路径长度

dist[j]=E.length+c[E.i][j];//更新dist数组

prev[j]=E.i;

//加入活结点优先队列

MinHeapNodeN;

N.i=j;

N.length=dist[j];

H.Insert(N);//插入到最小堆中

}

try

{

H.DeleteMin(E);//取下一扩展结点

}

catch(int)

{

break;

}

if(H.currentsize==0)//优先队列空

{

break;

}

}

}

测试结果

上述有向图的结果:

 

实验分析

在实验中并没有生成多组数据,进行比较,也没有利用随机生成函数,因为在这种有实际有关联的问题中,利用随机生成函数生成的数据是十分的不合适的,在此我们只需要验证该程序是否正确即可。

分支限界法求单源最短路径问题与回溯法求单源最短路径问题其大致思想是一致的,都是利用解空间树,搜索子集树,回溯法是利用深度优先搜索子集树,而分支限界法是利用广度优先搜索子集树,然后利用队列或优先队列,最小堆存放可扩展的结点,然后将活结点出堆,从而直到堆空为止,找到最优解。

实验心得

在这一章的分支限界法中,与上一章的回溯法很相似,都是利用解空间树进行搜索,从而找到最优解。

不同的是回溯法利用的是深度优先回溯寻找,能够找到所有的最优解;而分支限界法则是利用广度优先搜索子集树或者排序树,利用队列或者优先级队列的数据结构组织所有满足的结点,这样只要找到一种最优解就可以了,想对于回溯法来说时间上相对利用的没有那么多。

在这一章的学习上,由于会利用最小堆/最大堆,所以代码看起来比较复杂,堆的实现也比较复杂,这是这一章我学习的一个难点,不过正在渐渐攻克。

实验得分

助教签名

附录:

完整代码(分支限界法)

Shorest_path.cpp

//单源最短路径问题分支限界法求解

#include

#include

#include

#include"MinHeap2.h"

usingnamespacestd;

template

classGraph//定义图类

{

friendintmain();

public:

voidshortest_path(int);

private:

intn,//图的顶点数

*prev;//前驱顶点数组

Type**c,//图的邻接矩阵

*dist;//最短距离数组

};

template

classMinHeapNode//最小堆中的元素类型为MinHeapNode

{

friendGraph;

public:

operatorint()const{returnlength;}

private:

inti;//顶点编号

Typelength;//当前路长

};

//单源最短路径问题的优先队列式分支限界法

template

voidGraph:

:

shortest_path(intv)

{

MinHeap>H(1000);//定义最小堆的容量为1000

//定义源为初始扩展结点

MinHeapNodeE;

//初始化源结点

E.i=v;

E.length=0;

dist[v]=0;

while(true)//搜索问题的解空间

{

for(intj=1;j<=n;j++)

if((c[E.i][j]!

=0)&&(E.length+c[E.i][j]

{

//顶点i到顶点j可达,且满足控制约束

//顶点i和j之间有边,且此路径小于原先从源点i到j的路径长度

dist[j]=E.length+c[E.i][j];//更新dist数组

prev[j]=E.i;

//加入活结点优先队列

MinHeapNodeN;

N.i=j;

N.length=dist[j];

H.Insert(N);//插入到最小堆中

}

try

{

H.DeleteMin(E);//取下一扩展结点

}

catch(int)

{

break;

}

if(H.currentsize==0)//优先队列空

{

break;

}

}

}

intmain()

{

intn=11;

intprev[12]={0,0,0,0,0,0,0,0,0,0,0,0};//初始化前驱顶点数组

intdist[12]={1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000};//初始化最短距离数组

cout<<"单源图的邻接矩阵如下:

"<

int**c=newint*[n+1];

for(inti=1;i<=n;i++)//输入图的邻接矩阵

{

c[i]=newint[n+1];

for(intj=1;j<=n;j++)

{

cin>>c[i][j];

}

}

intv=1;//源结点为1

GraphG;

G.n=n;

G.c=c;

G.dist=dist;

G.prev=prev;

clock_tstart,end,over;//计算程序运行时间的算法

start=clock();

end=clock();

over=end-start;

start=clock();

G.shortest_path(v);//调用图的最短路径查找算法

//输出从源结点到目的结点的最短路径

cout<<"从S到T的最短路长是:

"<

for(inti=2;i<=n;i++)//输出每个结点的前驱结点

{

cout<<"prev("<

}

for(inti=2;i<=n;i++)//输出从源结点到其他结点的最短路径长度

{

cout<<"从1到"<

"<

}

for(inti=1;i<=n;i++)//删除动态分配时的内存

{

delete[]c[i];

}

delete[]c;

c=0;

end=clock();

printf("Thetimeis%6.3f",(double)(end-start-over)/CLK_TCK);//显示运行时间

cout<

system("pause");

return0;

}

MinHeap.h

#include

template

classGraph;

template

classMinHeap//最小堆类

{

template

friendclassGraph;

public:

MinHeap(intmaxheapsize=10);//构造函数,堆的大小是10

~MinHeap(){delete[]heap;}//最小堆的析构函数

intSize()const{returncurrentsize;}//Size()返回最小堆的个数

TMax(){if(currentsize)returnheap[1];}//第一个元素出堆

MinHeap&Insert(constT&x);//最小堆的插入函数

MinHeap&DeleteMin(T&x);//最小堆的删除函数

voidInitialize(Tx[],intsize,intArraySize);//堆的初始化

voidDeactivate();

voidoutput(Ta[],intn);

private:

intcurrentsize,maxsize;

T*heap;

};

template

voidMinHeap:

:

output(Ta[],intn)//输出函数,输出a[]数组的元素

{

for(inti=1;i<=n;i++)

cout<

cout<

}

 

template

MinHeap:

:

MinHeap(intmaxheapsize)

{

maxsize=maxheapsize;

heap=newT[maxsize+1];//创建堆

currentsize=0;

}

template

MinHeap&MinHeap:

:

Insert(constT&x)

{

if(currentsize==maxsize)//如果堆中的元素已经等于堆的最大大小

return*this;//那么不能在加入元素进入堆中

inti=++currentsize;

while(i!

=1&&x

{

heap[i]=heap[i/2];

i/=2;

}

heap[i]=x;

return*this;

}

template

MinHeap&MinHeap:

:

DeleteMin(T&x)//删除堆顶元素

{

if(currentsize==0)

{

cout<<"Emptyheap!

"<

return*this;

}

x=heap[1];

Ty=heap[currentsize--];

inti=1,ci=2;

while(ci<=currentsize)

{

if(ciheap[ci+1])

ci++;

if(y<=heap[ci])

break;

heap[i]=heap[ci];

i=ci;

ci*=2;

}

heap[i]=y;

return*this;

}

template

voidMinHeap:

:

Initialize(Tx[],intsize,intArraySize)//堆的初始化

{

delete[]heap;

heap=x;

currentsize=size;

maxsize=ArraySize;

for(inti=currentsize/2;i>=1;i--)

{

Ty=heap[i];

intc=2*i;

while(c<=currentsize)

{

if(cheap[c+1])

c++;

if(y<=heap[c])

break;

heap[c/2]=heap[c];

c*=2;

}

heap[c/2]=y;

}

}

template

voidMinHeap:

:

Deactivate()

{

heap=0;

}

 

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 自然科学 > 物理

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1