单源点最短路径 c++实现 分支限界算法

问题描述:在一个网(带权图)中,从指定节点出发,找到到各个节点的最短路径

 

分支限界思想:

一个问题的解空间可以用一棵树来表示,比如此题,在此题的解空间树中,根是指定节点,任何一个节点的子女是与此节点连接的除父节点之外的所有节点。

当使用分支限界思想来解决此题时,在广度遍历此树的过程中,及时对那些不可能的子树进行剪枝。

用一个最小堆来存储活节点表,其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;
}
    原文作者:分支限界法
    原文地址: https://blog.csdn.net/longzuo/article/details/45969053
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞