// 單源最短路徑Dijkstra算法實現.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include<iostream>
#define MAX 200
#define Infinity 65535
using namespace std;
//邊尾節點信息結構體
struct edgeNode
{
int no; //尾接點序號
int cost; //邊權值
edgeNode *next; //其下一條鄰接邊尾節點指針
};
//節點信息結構體
struct vexNode
{
char info; //節點名稱
edgeNode *link; //與其相連的邊的尾節點鏈表指針
};
struct Queue
{
int no; //隊列中節點序號
int cost; //以此為尾節點的邊的權值
};
//優先隊列
Queue priQue[MAX];
//節點數組
vexNode adjlist[MAX];
//指定源點到節點i的最短路徑花費
int lowcost[MAX];
//指定源點到節點i路徑中,節點i的前驅節點序號
int parent[MAX];
//建立圖鄰接表
void createGraph(vexNode *adjlist,int *parent,int * lowcost,const int n,const int e)
{
int i;
for(i=1;i<=n;i++)
{
cout<<"請輸入節點"<<i<<"的名稱:";
cin>>adjlist[i].info;
adjlist[i].link = NULL;
lowcost[i] = Infinity;
parent[i] = i;
}
edgeNode *p1;
int v1,v2;
for(i=1;i<=e;i++)
{
cout<<"請輸入邊"<<i<<"的起始節點與尾節點序號:";
cin>>v1>>v2;
p1 = (edgeNode*)malloc(sizeof(edgeNode));
p1->no = v2;
cout<<"此邊的權值:";
cin>>p1->cost;
p1->next = adjlist[v1].link;
adjlist[v1].link = p1;
}
}
//當插入節點到優先隊列時,保持隊列優先性
void keep_min_heap(Queue *priQue,int &num,const int k)
{
int l = 2*k;
int r = 2*k + 1;
int smallest = k;
if(l<=num&&priQue[l].cost<priQue[k].cost)
smallest = l;
if(r<=num&&priQue[r].cost<priQue[smallest].cost)
smallest = r;
if(smallest != k)
{
Queue temp = priQue[smallest];
priQue[smallest] = priQue[k];
priQue[k] = temp;
keep_min_heap(priQue,num,smallest);
}
}
//插入節點到優先隊列時並且保持隊列優先性
void heap_insert(Queue *priQue,int &num,int no,int cost)
{
num +=1;
priQue[num].no = no;
priQue[num].cost = cost;
int i = num;
while(i>1&&priQue[i/2].cost>priQue[i].cost)
{
Queue temp = priQue[i];
priQue[i] = priQue[i/2];
priQue[i/2] = temp;
i = i/2;
}
}
//取出優先隊列的隊頭元素
Queue heap_extract_min(Queue *priQue,int &num)
{
if(num<1)
return priQue[0];
Queue min = priQue[1];
priQue[1] = priQue[num];
num -=1;
keep_min_heap(priQue,num,1);
return min;
}
//打印指定源點帶序號為i的點的最短路徑
void print_it(int *parent,vexNode *adjlist,int v)
{
if(parent[v] == v)
cout<<"("<<v<<":"<<adjlist[v].info<<") ";
else
{
print_it(parent,adjlist,parent[v]);
cout<<"("<<v<<":"<<adjlist[v].info<<") ";
}
}
int _tmain(int argc, _TCHAR* argv[])
{
int cases;
cout<<"請輸入案例的個數:";
cin>>cases;
while(cases--)
{
int n,e;
cout<<"請輸入節點數:";
cin>>n;
cout<<"請輸入邊數:";
cin>>e;
//隊列中的元素,初始為0
int num = 0;
int i;
//創建鄰接表
createGraph(adjlist,parent,lowcost,n,e);
cout<<endl;
cout<<"從哪個節點開始:";
int v0;
cin>>v0;
int v =v0;
lowcost[v0] = 0;
cout<<endl;
Queue queue;
for(i=1;i<n;i++)
{
edgeNode *p = adjlist[v0].link;
while(p != NULL)
{
if(lowcost[v0] + p->cost<lowcost[p->no])
{
lowcost[p->no] = lowcost[v0] + p->cost;
parent[p->no] = v0;
heap_insert(priQue,num,p->no,lowcost[p->no]);
}
p = p->next;
}
queue = heap_extract_min(priQue,num);
v0 = queue.no;
}
for(i=1;i<=n;i++)
{
mincost = 0;
cout<<"從點"<<adjlist[v].info<<"開始到"<<adjlist[i].info<<"的最短路徑為:"<<endl;
print_it(parent,adjlist,i);
cout<<endl;
cout<<"距離為:"<<lowcost[i]<<endl;
}
}
system("pause");
return 0;
}
--------------------------------------------------程序測試-----------------------------------------------------
請輸入案例的個數:1
請輸入節點數:5
請輸入邊數:10
請輸入節點1的名稱:a
請輸入節點2的名稱:b
請輸入節點3的名稱:c
請輸入節點4的名稱:d
請輸入節點5的名稱:e
請輸入邊1的起始節點與尾節點序號:1 2
此邊的權值:10
請輸入邊2的起始節點與尾節點序號:1 4
此邊的權值:5
請輸入邊3的起始節點與尾節點序號:2 3
此邊的權值:1
請輸入邊4的起始節點與尾節點序號:2 4
此邊的權值:2
請輸入邊5的起始節點與尾節點序號:3 5
此邊的權值:4
請輸入邊6的起始節點與尾節點序號:4 2
此邊的權值:3
請輸入邊7的起始節點與尾節點序號:4 3
此邊的權值:9
請輸入邊8的起始節點與尾節點序號:4 5
此邊的權值:2
請輸入邊9的起始節點與尾節點序號:5 1
此邊的權值:7
請輸入邊10的起始節點與尾節點序號:5 3
此邊的權值:6
從哪個節點開始:1
從點a開始到a的最短路徑為:
(1:a)
距離為:0
從點a開始到b的最短路徑為:
(1:a) (4:d) (2:b)
距離為:8
從點a開始到c的最短路徑為:
(1:a) (4:d) (2:b) (3:c)
距離為:9
從點a開始到d的最短路徑為:
(1:a) (4:d)
距離為:5
從點a開始到e的最短路徑為:
(1:a) (4:d) (5:e)
距離為:7
請按任意鍵繼續. .
作者 heyongluoyao8