Dijkstraアルゴリズムは非負の重み値の最短経路の解を実現する(小根スタックを用いて最適化する)
Dijkstraアルゴリズムを用いて非負の重み値の最小値を解くには,n−1ラウンドのループを行い,各ラウンドは,片側条件下で開始ノードv 0から他の各ノードまでの最短距離を求め,隣接するこの点v 1を「処理済み」と表記し,v 1を中継としてv 1に最も近い残りの頂点v 2を見つけ,次にdist[v 2]の値とdist[v 1]+weight[v 1][v 2]を比較し、dist[v 2]が大きい場合はdist[v 2]をdist[v 1]+weight[v 1][v 2]に書き換える.
基本的な実装は次のとおりです.
しかし、上記のコードを分析すると、開始点に最も近いノードを探すときに、何度も比較を繰り返し、優先キューまたは小さなルートスタックを使用して、実際のノードに最も近いノードを迅速に見つけることができます.
基本的な実装は次のとおりです.
#include <iostream>
#include <memory.h>
using namespace std;
const int MaxSize=10;
int arr[MaxSize][MaxSize];
int dist[MaxSize];
int numNode=0; //
//
void createArr()
{
//
cin>>numNode;
for(int i=0;i<numNode;++i)
for(int j=0;j<numNode;++j)
cin>>arr[i][j];
}
//
void Dijkstra(int v0)
{
memset(dist,0,sizeof(dist));
// v0
for(int i=0;i<numNode;++i)
dist[i]=arr[v0][i];
int pos=0;
arr[v0][v0]=1; // v0 1
// numNode-1 v0
for(int i=0;i<numNode-1;++i)
{
int min=32767;
// v0
for(int k=0;k<numNode;++k)
{
if((dist[k]<min)&&(arr[k][k]!=1))
{
pos=k;
min=dist[k];
}
}
arr[pos][pos]=1; // 1
// pos , if v0
for(int j=0;j<numNode;++j)
{
if((arr[j][j]!=1)&&(arr[pos][j]+min<dist[j]))
dist[j]=arr[pos][j]+min;
}
}
//
for(int i=0;i<numNode;++i)
cout<<dist[i]<<" ";
cout<<endl;
}
int main()
{
createArr();
Dijkstra(0);
}
しかし、上記のコードを分析すると、開始点に最も近いノードを探すときに、何度も比較を繰り返し、優先キューまたは小さなルートスタックを使用して、実際のノードに最も近いノードを迅速に見つけることができます.
#include <iostream>
#include <memory.h>
using namespace std;
/*************************** **********************/
struct Heap
{
int link; //
int dist;//
} heap[60];
//
void siftDown(int start,int end)
{
// start end
int i=start,j=2*i;
heap[0]=heap[i]; // heap[0] i
while(j<=end)
{
// , j j
if(j<end&&heap[j].dist>heap[j+1].dist) ++j;
// j ,
if(heap[0].dist<heap[j].dist)
break;
else
{
//
heap[i]=heap[j];
i=j;
j=2*j;
}
}
heap[i]=heap[0];
}
//
// start 1
void siftUp(int start)
{
int j=start,i=j/2;
heap[0]=heap[j];
while(j>0)
{
// ,numID
if(heap[i].dist<heap[0].dist)
break;
else
{
//
heap[j]=heap[i];
j=i;
i=i/2;
}
}
heap[j]=heap[0];
}
//
bool insert(int& num,Heap& temp)
{
++num;
heap[num]=temp;
siftUp(num);
return true;
}
//
bool removeMin(int& num,Heap& temp)
{
if(0==num)
return false;
//
temp=heap[1];
heap[1]=heap[num]; //
--num;
siftDown(1,num); //
return true;
}
/******************************* ****************************/
const int MaxSize=10;
int arr[MaxSize][MaxSize]; //
int dist[MaxSize]; //
int numNode=0; //
//
void createArr()
{
//
cin>>numNode;
for(int i=0;i<numNode;++i)
for(int j=0;j<numNode;++j)
cin>>arr[i][j];
}
//
void Dijkstra(int v0)
{
memset(dist,0,sizeof(dist));
// v0
for(int i=0;i<numNode;++i)
dist[i]=arr[v0][i];
arr[v0][v0]=1; // v0 1
int num=0; //
Heap temp;
// numNode-1 v0
for(int i=0;i<numNode-1;++i)
{
//
for(int k=0;k<numNode;++k)
{
if(arr[k][k]!=1)
{
temp.link=k;
temp.dist=dist[k];
insert(num,temp);
}
}
// v0
if(!removeMin(num,temp)) return;
int pos=temp.link;
int min=temp.dist;
arr[pos][pos]=1; // 1
// pos , v0
for(int j=0;j<numNode;++j)
{
if((arr[j][j]!=1)&&(arr[pos][j]+min<dist[j]))
{
dist[j]=arr[pos][j]+min;
//
temp.link=j;
temp.dist=dist[j];
insert(num,temp);
}
}
}
// v0
for(int i=0;i<numNode;++i)
cout<<dist[i]<<" ";
cout<<endl;
}
int main()
{
createArr();
Dijkstra(0);
}