dijkstra演算法筆記(C語言實現,顯示路徑)
dijkstra演算法(迪傑斯特拉演算法)筆記(C語言實現,顯示路徑)
具體描述每一步的執行情況
在學習完廣度優先搜尋之後,瞭解了在無權圖中怎麼找出最短路徑。但廣度優先搜尋解決不了當邊具有權值的情況。
dijkstra演算法就是解決這種情況的演算法。
一個具有邊權的圖:
現在,以1位初始點,找出各點到1的最短距離,並且顯示路徑。
首先建立一個結構陣列,來儲存各點的資訊:
struct item{
int key; //這個點是否被訪問
int dis; //這個點到原點的距離
int n_number; //路徑中有多少個點
int n[10]; //建立陣列來儲存路徑
};
struct item dist[9]; //這個圖中有9個點
從1開始,與1相連的2,8都沒有被訪問過,進入佇列,並更新這些點的資訊:
現在,佇列頭是2,於是2出佇列,與2相關聯且滿足條件的進入佇列(滿足條件應分兩種情況;1.若這個點沒有被訪問,直接進入佇列。2.若這個點已經被訪問,但新路徑的距離比原路徑的距離要短,這個點也入隊,更新資訊),更新各點的資訊:
在上一步中,8雖然已經被訪問過了,但更新之後8由路徑(1-2-8)到1的距離為7,比之前的要小,所以點8的各項資訊被更新,進入對列,所以現在佇列中的(8,3,8)兩個8具有一樣的資訊。
現在,與8相關的點進入佇列,8出佇列:更新後的資訊:
繼續操作,3出隊,與3相關的點入隊:
這裡4,還沒有被訪問,直接入隊,
9已經被訪問,但9目前的距離為8,比12+2要小,9,不用入隊。
現在,由於8已經被操作過,所以,8單純出隊,沒有元素入隊:
接著,7出隊,6入隊
接著,在9出隊,且與9相連的點中,3滿足更新條件(3目前距離為12,更新後為8+2=10),3入隊:
4出隊,5入隊
至此所有元素都已經訪問完畢,但佇列並不為空,意味著仍然有元素可能會被更新
6出隊,5滿足更新條件,5入隊
繼續執行,3出隊,4滿足更新條件,入隊:
接下來的兩個5單純出隊,沒有任何元素滿足入隊條件:
最後4出隊,同樣沒有元素滿足更新條件,沒有元素入隊,佇列為空。演算法結束。
最終結果如下:
程式碼與測試資料`
#include<stdlib.h>
#include<string.h>
#include<stdio.h>
struct node;
typedef struct node * pNode;
struct node{
int num;
int power;
pNode next;
};
struct item{
int key; //這個點是否被訪問
int dis; //這個點到原點的距離
int n_number; //路徑中有多少個點
int n[10]; //建立陣列來儲存路徑
};
struct queue;
typedef struct queue * pQueue;
struct queue{
int num;
pQueue next;
};
pQueue add(pQueue,pQueue);
pQueue out(pQueue);
void show(pNode *,int);
int main()
{
pNode * list;
int a,b,c,N,i,j;
pNode current,temp;
scanf("%d",&N);
list=(pNode *)malloc(sizeof(pNode)*N);
for(i=0;i<N;i++){
list[i]=(pNode)malloc(sizeof(struct node));
temp=list[i];
temp->num=i+1;
temp->next=NULL;
while(scanf("%d",&a)==1){
current=(pNode)malloc(sizeof(struct node));
current->num=a;
scanf("%d",&b);
current->power=b;
current->next=NULL;
temp->next=current;
temp=current;
}
getchar();
}
show(list,N);
//儲存完畢,開始搜尋
struct item dist[N];
for(i=0;i<N;i++){
dist[i].key=0;
dist[i].dis=0;
dist[i].n_number=0;
}
//以第一個點為初始點
dist[0].key=1;
dist[0].dis=0;
int dis=0 ,count=1,x[10];
x[0]=1;
pQueue head=NULL,kong;
current=list[0]->next;
do{
while(current!=NULL){
if(dist[current->num-1].key==0){//第一次遇到,直接入隊
dist[current->num-1].key=1;
dist[current->num-1].dis=dis+current->power;
kong=(pQueue)malloc(sizeof(struct queue));
kong->num=current->num;
head=add(head,kong);
//開始複製陣列;
for(i=0;i<count;i++)
dist[current->num-1].n[i]=x[i];
dist[current->num-1].n[count]=current->num;
dist[current->num-1].n_number=count+1;
}
else if(dist[current->num-1].dis>dis+current->power){
dist[current->num-1].dis=dis+current->power;
kong=(pQueue)malloc(sizeof(struct queue));
kong->num=current->num;
head=add(head,kong);
//開始複製陣列;
for(i=0;i<count;i++)
dist[current->num-1].n[i]=x[i];
dist[current->num-1].n[count]=current->num;
dist[current->num-1].n_number=count+1;
}
current=current->next;
}
current=list[head->num-1]->next;
count=dist[head->num-1].n_number;
for(i=0;i<count;i++)
x[i]=dist[head->num-1].n[i];
dis=dist[head->num-1].dis;
head=out(head);
while(current!=NULL){
if(dist[current->num-1].key==0){//第一次遇到,直接入隊
dist[current->num-1].key=1;
dist[current->num-1].dis=dis+current->power;
kong=(pQueue)malloc(sizeof(struct queue));
kong->num=current->num;
head=add(head,kong);
//開始複製陣列;
for(i=0;i<count;i++)
dist[current->num-1].n[i]=x[i];
dist[current->num-1].n[count]=current->num;
dist[current->num-1].n_number=count+1;
}
else if(dist[current->num-1].dis>dis+current->power){
dist[current->num-1].dis=dis+current->power;
kong=(pQueue)malloc(sizeof(struct queue));
kong->num=current->num;
head=add(head,kong);
//開始複製陣列;
for(i=0;i<count;i++)
dist[current->num-1].n[i]=x[i];
dist[current->num-1].n[count]=current->num;
dist[current->num-1].n_number=count+1;
}
current=current->next;
}
}while(head!=NULL);
for(i=0;i<N;i++){
if(dist[i].dis==0){
printf("元素:%d 原點",i+1);
}
else{
printf("元素:%d 距離:%d",i+1,dist[i].dis);
printf(" 路徑:");
for(j=0;j<dist[i].n_number;j++){
printf("%d--",dist[i].n[j]);
}
printf("\n");
}
}
}
void show(pNode *list,int N)
{
int i;
pNode current;
for(i=0;i<N;i++)
{
printf("%d -> ",list[i]->num);
current=list[i]->next;
while(current!=NULL){
printf("%d(%d) ",current->num,current->power);
current=current->next;
}
puts("");
}
}
pQueue out(pQueue head)
{
if(head->next==NULL){
free(head);
return NULL;
}
else{
pQueue temp=head->next;
free(head);
return temp;
}
}
pQueue add(pQueue head,pQueue current)
{
if(head==NULL){
head=current;
current->next=NULL;
}
else{
pQueue temp=head;
while(temp->next!=NULL)
temp=temp->next;
temp->next=current;
current->next=NULL;
}
return head;
}
測試資料:
9
2 4 8 8 +
1 4 8 3 3 8 +
2 8 9 2 4 7 +
3 7 6 14 5 9 +
4 9 6 10 +
4 14 5 10 7 2 +
6 2 9 6 8 6 +
7 6 9 1 2 3 1 8 +
3 2 7 6 8 1 +
以輸入非數字符號結束,所以後面有一個加號
以雜湊表(那個形式,沒有雜湊函式)儲存圖的結構:
1 -> :2(4) 8(8)
2 -> :1(4) 8(3) 3(8)
3 -> :2(8) 9(2) 4(7)
4 -> :3(7) 6(14) 5(9)
5 -> :4(9) 6(10)
6 -> :4(14) 5(10) 7(2)
7 -> :6(2) 9(6) 8(6)
8 -> :7(6) 9(1) 2(3) 1(8)
9 -> :3(2) 7(6) 8(1)
最後的輸出結果:
相關文章
- 最短路徑——dijkstra演算法程式碼(c語言)演算法C語言
- c語言筆記C語言筆記
- 排序演算法-C語言實現排序演算法C語言
- PID演算法的C語言實現演算法C語言
- python實現Dijkstra演算法之 最短路徑問題Python演算法
- 【CRC筆記】CRC-16 MAXIM-DOW C語言實現筆記C語言
- C 語言學習筆記筆記
- C語言學習筆記C語言筆記
- C語言指標筆記C語言指標筆記
- 最短路徑——floyd演算法程式碼(c語言)演算法C語言
- C語言實現九大排序演算法C語言排序演算法
- C語言學習筆記--C運算子C語言筆記
- 最短路徑--dijkstra演算法、弗洛伊德(Floyd)演算法(帶路徑輸出)演算法
- [最短路徑問題]Dijkstra演算法(含還原具體路徑)演算法
- 最短路徑之Dijkstra演算法演算法
- 經典排序演算法的 C語言 | Java 實現排序演算法C語言Java
- 路徑規劃演算法 - 求解最短路徑 - Dijkstra(迪傑斯特拉)演算法演算法
- c語言學習筆記===函式C語言筆記函式
- C語言筆記——自定義型別C語言筆記型別
- 掃雷--C語言實現C語言
- c語言實現階乘C語言
- 【作業系統】銀行家演算法實現(C語言)作業系統演算法C語言
- 最短路徑問題 (dijkstra演算法)演算法
- 單源最短路徑-Dijkstra演算法演算法
- 初識C語言(01)—學習筆記C語言筆記
- C語言學習筆記——位運算C語言筆記
- c語言程式基礎學習筆記C語言筆記
- C語言學習筆記之變數C語言筆記變數
- 考研:C語言複習筆記 [Hex Note]C語言筆記
- c語言筆記:楊輝三角C語言筆記
- 調查顯示,富裕國家流行 Python 和 C 語言Python
- 斐波那契數列 多語言實現 筆記筆記
- 使用jquery.i18n實現國際化多語言顯示jQuery
- C語言__LINE__實現原理C語言
- C語言實現檔案加密C語言加密
- c語言實現this指標效果C語言指標
- 高精度加法(C語言實現)C語言
- C語言實現TCP通訊C語言TCP