问题描述:在一个网(带权图)中,从指定节点出发,找到到各个节点的最短路径
分支限界思想:
一个问题的解空间可以用一棵树来表示,比如此题,在此题的解空间树中,根是指定节点,任何一个节点的子女是与此节点连接的除父节点之外的所有节点。
当使用分支限界思想来解决此题时,在广度遍历此树的过程中,及时对那些不可能的子树进行剪枝。
用一个最小堆来存储活节点表,其key是对应节点到指定节点的“当前距离”
算法从图的指定节点S和空堆开始,节点s被扩展后,它的儿子节点被依次插入堆中,伺候,算法从堆中取出具有最小当前距离的节点最为当前的扩展节点,病依次检查与当前扩展节点相邻的所有定点。如果从当前扩展节点i到顶点j有边可达并且从源点出发,途径顶点i在到顶点j的所相应的路径的长度小于当前最优路径长度,则将该顶点j作为活节点插入到活节点优先队列中,这个节点的扩展过程一直继续到活节点优先队列为空为止
////////////////minHeap.h////////////////////////////////////////
#ifndef MINHEAP
#define MINHEAP
template <class T>
class MinHeap
{
private:
T *heap;
int capacity;
int size;
void heapAdjust(int,int);
public:
MinHeap(int);
~MinHeap();
void heapDelete(T &);//删除最小元素,并带回
void insert(T &);//插入堆
bool empty()const;//判断堆是否为空
};
class noMem
{};
class outOfBound
{};
template <class T>
MinHeap<T>::MinHeap(int n)
{
heap=new T[n+1];
capacity=n;
size=0;
}
template <class T>
MinHeap<T>::~MinHeap()
{
delete[] heap;
}
template <class T>
void MinHeap<T>::heapDelete(T &e)
{
if(empty())throw outOfBound();
T temp;
temp=heap[1];heap[1]=heap[size];heap[size]=temp;
e=heap[size];
size--;
heapAdjust(1,size);
}
//向最小堆中插入一个元素
//从刚插入元素的父节点开始,逐层向上调整,
//每次调整都是:将一个除根节点外,已经是最小堆的二叉树调整为一个最小堆
template <class T>
void MinHeap<T>::insert(T &e)
{
if(size+1>capacity)throw noMem();
size++;
heap[size]=e;
for(int i=(size)/2;i>=1;i/=2)
heapAdjust(i,size);
}
//最小堆类中最核心的一个函数
//其作用是将一个除根外,其他部分都已经满足最小堆定义的二叉树 调整为一个最小堆
template <class T>
void MinHeap<T>::heapAdjust(int start,int end)
{
T temp=heap[start];
int i;
for(i=start*2;i<=end;i*=2)//从start的下一行开始找比temp大的 start一直保持在当前处理层的上层
{
if(i+1<=end&&heap[i]>heap[i+1])i++;//先找到某对左右子树的小者,用i指向
if(heap[i]>=temp)break;//如果这个小者都比temp大 那么说明他两个都比temp大 temp就该成为他们的父亲
heap[start]=heap[i];//否则就把小的那个推举到高一层,然后处理下一层
start=i;
}
heap[start]=temp; //最后为temp找到归宿
}
template <class T>
bool MinHeap<T>::empty()const
{
return size==0?true:false;
}
#endif
///////////////////////minHeapNode.h/////////////////////
#ifndef MINHEAPNODE
#define MINHEAPNODE
class minHeapNode
{
private:
int distance;
int number;
public:
minHeapNode(int n=0,int d=0);
int dist(){return distance;}
int num(){return number;}
};
minHeapNode::minHeapNode(int n,int d)
{
distance=d;
number=n;
}
bool operator <(minHeapNode &n,minHeapNode &m)
{
return n.dist()<m.dist()?true:false;
}
bool operator >(minHeapNode &n,minHeapNode &m)
{
return n.dist()>m.dist()?true:false;
}
bool operator >=(minHeapNode &n,minHeapNode &m)
{
return n.dist()>=m.dist()?true:false;
}
bool operator <=(minHeapNode &n,minHeapNode &m)
{
return n.dist()<=m.dist()?true:false;
}
#endif
////////////graphic.h//////////////////////////////////////
#ifndef GRAPHIC
#define GRAPHIC
#include "minHeap.h"
#include "minHeapNode.h"
#define INF 65535
template <class T>
class graphic
{
private:
int **m;//临接矩阵
int n;//顶点个数
int *dist;//从源点到每点的最短距离组成的数组
T *v;//顶点数组
int *prev;//路径上每一个顶点的前一个顶点下标组成的数组
public:
graphic(T *vv,int **mm,int nn);
~graphic();
void shortestPath(int);
void result()};
template <class T>
graphic<T>::graphic(T *vv,int **mm,int nn)//给各个数组开辟空间并用参数数组填充
{
n=nn;
v=new T[n+1];
dist=new int[n+1];
prev=new int[n+1];
for(int i=1;i<=n;i++)
{
v[i]=vv[i];
dist[i]=INF;
prev[i]=0;
}
m=new int*[n+1];
for(i=0;i<=n;i++)
m[i]=new int[n+1]; //动态分配二维数组
for(i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
m[i][j]=mm[i][j];
}
}
template <class T>
graphic<T>::~graphic()
{
delete []v;
delete []dist;
delete []prev;
for(int i=0;i<=n;i++)
delete [] m[i]; //删除动态分配的二维数组
delete []m;
}
template <class T>
void graphic<T>::shortestPath(int s)
{
MinHeap<minHeapNode> mh(100);
minHeapNode N(s,0);
mh.insert(N);
while(!mh.empty())
{
mh.heapDelete(N);
for(int i=1;i<=n;i++)
{
if(m[N.num()][i]!=INF&&dist[i]>m[N.num()][i]+N.dist())
{
dist[i]=m[N.num()][i]+N.dist();
prev[i]=N.num();
mh.insert(minHeapNode(i,dist[i]));
}
}
}
}
template <class T>
void graphic<T>::result()
{
for(int i=2;i<=n;i++)
{
int j=i;
while(j!=1)
{
cout<<v[j]<<" ";
j=prev[j];
}
cout<<v[j]<<" dist: "<<dist[i]<<endl;
}
}
#endif
///////////////////////////main.cpp////////////////////////
#include <iostream>
#include "graphic.h"
#include "minHeap.h"
#include "minHeapNode.h"
using namespace std;
int main()
{
int m[12][12]=
{
{INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF},
{INF,INF,2,3,4,INF,INF,INF,INF,INF,INF,INF},
{INF,INF,INF,3,INF,7,2,INF,INF,INF,INF,INF},
{INF,INF,INF,INF,INF,INF,9,2,INF,INF,INF,INF},
{INF,INF,INF,INF,INF,INF,INF,2,INF,INF,INF,INF},
{INF,INF,INF,INF,INF,INF,INF,INF,5,7,INF,INF},
{INF,INF,INF,INF,INF,INF,INF,1,INF,3,INF,INF},
{INF,INF,INF,INF,INF,INF,INF,INF,INF,5,1,INF},
{INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,1},
{INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,3},
{INF,INF,INF,INF,INF,INF,INF,INF,INF,2,INF,7},
{INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF}
};
int **mm;
mm=new int* [12];
for(int i=0;i<=11;i++)
mm[i]=new int[12];
for(i=1;i<=11;i++)
for(int j=1;j<=11;j++)
mm[i][j]=m[i][j];
char c[12];
char temp='a';
for(i=1;i<=11;i++)
{
c[i]=temp++;
}
graphic<char> g(c,mm,11);
g.shortestPath(1);
g.result();
/**/
return 1;
}