========================================================================
這主要是用來找起點與終點最短路徑的方法,搜索是以目標節點全遍歷的方式進行搜索,一步步確定每個節點的最短路徑才終止.
操作過程中分兩集合: 確定最短路徑頂點集合U 與 未確定最短路徑頂點集合V. 利用U裏面的有向向量鏈分別搜索V裏面的每個節點,形成的最短鏈對應的那個節點就可以確定最短路徑了,其就可以加入集合U,逐步搜索整個集合V,直到V中數量減小到零,全部確定.
========================================================================
先上基本搜索步驟圖對算法理解.轉自:圖之Dijkstra算法
Dijkstra算法是一種求單源最短路的算法,即從一個點開始到所有其他點的最短路。其步驟如下: (原文鏈接有參考代碼.)
既然理解了搜索步驟,那我們看看其中的思想. 參見:最短路徑之Dijkstra算法詳細講解
1 最短路徑算法
在日常生活中,我們如果需要常常往返A地區和B地區之間,我們最希望知道的可能是從A地區到B地區間的衆多路徑中,那一條路徑的路途最短。最短路徑問題是圖論研究中的一個經典算法問題, 旨在尋找圖(由結點和路徑組成的)中兩結點之間的最短路徑。 算法具體的形式包括:
(1)確定起點的最短路徑問題:即已知起始結點,求最短路徑的問題。
(2)確定終點的最短路徑問題:與確定起點的問題相反,該問題是已知終結結點,求最短路徑的問題。在無向圖中該問題與確定起點的問題完全等同,在有向圖中該問題等同於把所有路徑方向反轉的確定起點的問題。
(3)確定起點終點的最短路徑問題:即已知起點和終點,求兩結點之間的最短路徑。
(4)全局最短路徑問題:求圖中所有的最短路徑。
用於解決最短路徑問題的算法被稱做“最短路徑算法”, 有時被簡稱作“路徑算法”。 最常用的路徑算法有:Dijkstra算法、A*算法、Bellman-Ford算法、Floyd-Warshall算法、Johnson算法。
2.1 Dijkstra算法
Dijkstra算法是典型最短路算法,用於計算一個節點到其他所有節點的最短路徑。主要特點是以起始點爲中心向外層層擴展,直到擴展到終點爲止。Dijkstra算法能得出最短路徑的最優解,但由於它遍歷計算的節點很多,所以效率低。
Dijkstra算法是很有代表性的最短路算法,在很多專業課程中都作爲基本內容有詳細的介紹,如數據結構,圖論,運籌學等等。
Dijkstra算法思想爲:
設G=(V,E)是一個帶權有向圖,把圖中頂點集合V分成兩組,
第一組爲已求出最短路徑的頂點集合(用S表示,初始時S中只有一個源點,以後每求得一條最短路徑 , 就將 加入到集合S中,直到全部頂點都加入到S中,算法就結束了),
第二組爲其餘未確定最短路徑的頂點集合(用U表示),按最短路徑長度的遞增次序依次把第二組的頂點加入S中。在加入的過程中,總保持從源點v到S中各頂點的最短路徑長度不大於從源點v到U中任何頂點的最短路徑長度。
此外,每個頂點對應一個距離,S中的頂點的距離就是從v到此頂點的最短路徑長度,U中的頂點的距離,是從v到此頂點只包括S中的頂點爲中間頂點的當前最短路徑長度。
(1)初始時,S只包含源點,即S=,v的距離爲0。U包含除v外的其他頂點,U中頂點u距離爲邊上的權(若v與u有邊)或 )(若u不是v的出邊鄰接點)。
(2)從U中選取一個距離v最小的頂點k,把k,加入S中(該選定的距離就是v到k的最短路徑長度)。
(3)以k爲新考慮的中間點,修改U中各頂點的距離;若從源點v到頂點u(u U)的距離(經過頂點k)比原來距離(不經過頂點k)短,則修改頂點u的距離值,修改後的距離值的頂點k的距離加上邊上的權。
(4)重複步驟(2)和(3)直到所有頂點都包含在S中。
2.4 Dijkstra算法舉例說明
如下圖,設A爲源點,求A到其他各頂點(B、C、D、E、F)的最短路徑。線上所標註爲相鄰線段之間的距離,即權值。(注:此圖爲隨意所畫,其相鄰頂點間的距離與圖中的目視長度不能一一對等)
圖一:Dijkstra無向圖
算法執行步驟如下表:【注:圖片要是看不到請到“相冊--日誌相冊”中,名爲“Dijkstra算法過程”的圖就是了】
========================= 轉自最短路徑之Dijkstra算法 =========================
dijkstra算法兩個應用題:
HDOJ 1874 暢通工程續,現有解法:www.wutianqi.com/?p=1894
HDOJ 2544 最短路,現有解法:www.wutianqi.com/?p=1892
參考:http://hi.baidu.com/zealot886/item/c8a499ee5795bcddeb34c950
數據結構(C語言版)
http://www.cnblogs.com/biyeymyhjob/archive/2012/07/31/2615833.html
推薦幾篇搜索算法相關的非常好的博文:
一、A*搜索算法
一(續)、A*,Dijkstra,BFS算法性能比較及A*算法的應用
二、Dijkstra
算法初探 (Dijkstra算法系列4篇文章)
二(續)、徹底理解Dijkstra算法
二(再續)、Dijkstra
算法+fibonacci堆的逐步c實現
二(三續)、Dijkstra
算法+Heap堆的完整c實現源碼
==============
代碼
-
#include <stdio.h>
-
#include <malloc.h>
-
#define VERTEXNUM 6
-
-
-
typedef struct edge{
-
int vertex;
-
int value;
-
struct edge* next;
-
}st_edge;
-
-
void createGraph(int (*edge)[VERTEXNUM], int start, int end, int value);
-
void displayGraph(int (*edge)[VERTEXNUM]);
-
void displayPath(st_edge** path, int startVertex,int* shortestPath);
-
void dijkstra(int (*edge)[VERTEXNUM], st_edge*** path, int** shortestPath, int startVertex, int* vertexStatusArr);
-
int getDistance(int value, int startVertex, int start, int* shortestPath);
-
void createPath(st_edge **path, int startVertex, int start, int end, int edgeValue);
-
-
int main(void){
-
-
int (*edge)[VERTEXNUM] = (int (*)[VERTEXNUM])malloc(sizeof(int)*VERTEXNUM*VERTEXNUM);
-
int i,j;
-
for(i=0;i<VERTEXNUM;i++){
-
for(j=0;j<VERTEXNUM;j++){
-
edge[i][j] = 0;
-
}
-
}
-
-
int* vertexStatusArr = (int*)malloc(sizeof(int)*VERTEXNUM);
-
for(i=0;i<VERTEXNUM;i++){
-
vertexStatusArr[i] = 0;
-
}
-
-
printf("after init:\n");
-
displayGraph(edge);
-
-
createGraph(edge,0,1,6);
-
createGraph(edge,0,3,5);
-
createGraph(edge,0,2,1);
-
createGraph(edge,1,2,5);
-
createGraph(edge,1,4,3);
-
createGraph(edge,2,4,6);
-
createGraph(edge,2,3,5);
-
createGraph(edge,2,5,4);
-
createGraph(edge,3,5,2);
-
createGraph(edge,4,5,6);
-
-
printf("after create:\n");
-
displayGraph(edge);
-
-
-
-
-
-
-
-
-
-
-
-
-
st_edge** path = NULL;
-
-
-
-
-
-
-
-
-
-
int* shortestPath = NULL;
-
-
int startVertex = 0;
-
-
dijkstra(edge, &path, &shortestPath, startVertex, vertexStatusArr);
-
printf("the path is:\n");
-
displayPath(path,startVertex,shortestPath);
-
-
free(edge);
-
free(path);
-
return 0;
-
}
-
-
void createGraph(int (*edge)[VERTEXNUM], int start, int end, int value){
-
edge[start][end] = value;
-
edge[end][start] = value;
-
}
-
-
void displayGraph(int (*edge)[VERTEXNUM]){
-
int i,j;
-
for(i=0;i<VERTEXNUM;i++){
-
for(j=0;j<VERTEXNUM;j++){
-
printf("%d ",edge[i][j]);
-
}
-
printf("\n");
-
}
-
}
-
-
void displayPath(st_edge** path, int startVertex,int* shortestPath){
-
int i;
-
st_edge* p;
-
for(i=0;i<VERTEXNUM;i++){
-
printf("Path from %d to %d:",startVertex,i);
-
p = *(path+i);
-
while(p != NULL){
-
printf("%d(%d) ",p->vertex,p->value);
-
p = p->next;
-
}
-
printf("\n");
-
printf("the count is:%d\n",shortestPath[i]);
-
}
-
}
-
-
void dijkstra(int (*edge)[VERTEXNUM], st_edge*** path, int** shortestPath, int startVertex, int* vertexStatusArr){
-
-
*path = (st_edge**)malloc(sizeof(st_edge*)*VERTEXNUM);
-
int i,j;
-
for(i=0;i<VERTEXNUM;i++){
-
if(i == startVertex){
-
st_edge* e = (st_edge*)malloc(sizeof(st_edge));
-
e->vertex = startVertex;
-
e->value = 0;
-
e->next = NULL;
-
(*path)[i] = e;
-
}else{
-
(*path)[i] = NULL;
-
}
-
}
-
-
*shortestPath = (int *)malloc(sizeof(int)*VERTEXNUM);
-
for(i=0;i<VERTEXNUM;i++){
-
if(i == startVertex){
-
(*shortestPath)[i] = 0;
-
}else{
-
(*shortestPath)[i] = -1;
-
}
-
}
-
-
vertexStatusArr[startVertex] = 1;
-
-
int shortest, distance,start, end, edgeValue, vNum = 1;
-
-
while(vNum < VERTEXNUM){
-
shortest = 9999;
-
for(i=0;i<VERTEXNUM;i++){
-
-
if(vertexStatusArr[i] == 1){
-
for(j=0;j<VERTEXNUM;j++){
-
-
if(vertexStatusArr[j] == 0){
-
-
if(edge[i][j] != 0 && (distance = getDistance(edge[i][j], startVertex, i, *shortestPath)) < shortest){
-
shortest = distance;
-
edgeValue = edge[i][j];
-
start = i;
-
end = j;
-
}
-
}
-
}
-
}
-
}
-
vNum++;
-
-
vertexStatusArr[end] = 1;
-
-
(*shortestPath)[end] = shortest;
-
-
createPath(*path, startVertex, start, end, edgeValue);
-
}
-
}
-
-
-
int getDistance(int value, int startVertex, int start, int* shortestPath){
-
if(start == startVertex){
-
return value;
-
}else{
-
return shortestPath[start] + value;
-
}
-
}
-
-
-
void createPath(st_edge **path, int startVertex, int start, int end, int edgeValue){
-
if(start == startVertex){
-
st_edge* newEdge = (st_edge*)malloc(sizeof(st_edge));
-
newEdge->vertex = end;
-
newEdge->value = edgeValue;
-
newEdge->next = NULL;
-
-
st_edge** p = path + end;
-
while((*p) != NULL){
-
p = &((*p)->next);
-
}
-
*p = newEdge;
-
}else{
-
st_edge** pCopySrc = path + start;
-
st_edge** pCopyDes = path + end;
-
st_edge* newEdge = NULL;
-
while((*pCopySrc) != NULL){
-
newEdge = (st_edge*)malloc(sizeof(st_edge));
-
*newEdge = **pCopySrc;
-
newEdge->next = NULL;
-
*pCopyDes = newEdge;
-
pCopySrc = &((*pCopySrc)->next);
-
pCopyDes = &((*pCopyDes)->next);
-
}
-
newEdge = (st_edge*)malloc(sizeof(st_edge));
-
newEdge->vertex = end;
-
newEdge->value = edgeValue;
-
newEdge->next = NULL;
-
*pCopyDes = newEdge;
-
}
-
}