1. 程式人生 > >無向圖鄰接連結串列的廣度優先搜尋

無向圖鄰接連結串列的廣度優先搜尋

個人認為圖的演算法看起來非常簡潔,但是實現起來需要基礎很紮實。因為經常會涉及多種簡單的資料結構,怎樣把他們恰當的串聯起來,不會報那種,空指標了,型別不匹配,實體型別不符合了等等。
在做無向圖鄰接連結串列廣度優先搜尋的時候,寫的很冒火,想去找別的博主的程式碼借鑑一下,發現大部分,真的是大部分,都是有問題的,有些甚至都執行不出來。於是硬著頭皮自己寫了。
第一步是分析:
無向圖裡面用到的資料結構一個是連結串列,這裡用到了兩次。一個連結串列用於存放每個元素的與之相連的元素,用了一個鄰接連結串列。還要考慮所有元素怎麼連成一張圖,前面的連結串列可以得到的散開的這種形式x1------x2,要把所有元素集合起來就能變成一張圖,我又用了一個連結串列給他所有元素存起來。那麼大的連結串列裡面就有所有元素,以及每個元素的相連元素。也就是說訪問這個連結串列就能得到這張圖的結構。
還用到了一個佇列,主要是需要用到先進先出的性質,為了使資料的相互聯絡更加緊密,在宣告佇列結構體的時候,我用到的是連結串列的指標。
剩下的就是從一個源節點開始不斷的入隊出隊了,這個思想並不複雜。

要注意的就是指標了,怎麼處理空的情況,在寫連結串列的時候要特別注意,這是這個程式碼最重要的部分,其他的都是在呼叫他,如果寫出問題了後面的訪問肯定是有問題的。
(下面程式碼是根據演算法導論來寫 的,要是沒看過的書的話可能不知道白色灰色黑色等是在幹嘛…其實就是在標明一種狀態,簡單說一下就是初始化都是白色,訪問到他了(也就是讓他入隊列了),他就變成灰色,當把它的相連的子結點都訪問完了(也就是他出隊列了),就標記成黑色)

#include "stdafx.h"
#include <stdio.h>
#include<stdlib.h>
#define N 5    //the total number of points
#define MAX 0x3f3f3f3f typedef enum Color { W, G, B }Corlor; //white gray black typedef struct point_ *point; typedef struct link_ *link; typedef struct link_ { link rear; //尾指標 point node; //資料域 link next; //指標域 link front; //頭指標 }l; typedef struct point_ //define points' property { int key;
int distance; Color c; link Adj; //other points connected to the point point parent; //parent is a precessor point next; //this is for queue }p; typedef struct queue_ //佇列 { link head; link tail; }*queue, q; link INI_LINK(link L) { L = (link)malloc(sizeof(l)); L->rear = NULL; L->node = NULL; L->next = NULL; L->front = NULL; return L; } link INSERT_LINK(link L, point dot) { link new_p = (link)malloc(sizeof(l)); new_p=INI_LINK(new_p); new_p->node = dot; new_p->next = NULL; if (L->front == NULL) { L->front = L->rear = new_p; } else { L->rear->next = new_p; L->rear = new_p; if (L->front->next == NULL) L->front->next = L->rear; } return L; } queue INI_QUEUE(queue que) { que = (queue)malloc(sizeof(q)); que->head = NULL; que->tail = NULL; return que; } void ENQUEUE(queue que, point x) { link new_p = (link)malloc(sizeof(l)); new_p = INI_LINK(new_p); new_p->node = x; new_p->next = NULL; if (que->head == NULL) { que->head = que->tail = new_p; } else { que->tail->next = new_p; que->tail = new_p; if (que->head->next == NULL) que->head->next = que->tail; } } void DEQUEUE(queue que) { if (que->head == NULL) { return; } if (que->head == que->tail) { que->head = que->head->next = NULL; que->tail = que->tail->next = NULL; } else { que->head = que->head->next; } } //////////////////////////////////////////以上是構造基本的資料結構 連結串列和佇列,為圖的操作打下基礎 point INI_POINT(int k) //初始化結點 { point m = (point)malloc(sizeof(p)); link x = (link)malloc(sizeof(l)); x->node = NULL; x->front = NULL; x->rear = NULL; x->next = NULL; m->Adj = x; m->parent = NULL; m->c = W; m->key = k; m->distance = MAX; m->next = NULL; return m; } point INI_SOURCE_POINT(point source) { source->c = G; source->distance = 0; return source; } /////////////////以上是初始化結點 void CONNECTION(point x1, point x2) //連線兩個結點 { x1->Adj = INSERT_LINK(x1->Adj, x2); x2->Adj = INSERT_LINK(x2->Adj, x1); } void BFS(link All_Point, point s) { queue Q=(queue)malloc(sizeof(q)); Q=INI_QUEUE(Q); ENQUEUE(Q, s); while (Q->tail != NULL) { link u = Q->head; printf("(%d, %d) ", u->node->key, u->node->distance); DEQUEUE(Q); while (u->node->Adj->front != NULL) { link v = u->node->Adj->front; if (v->node->c == W) { v->node->c = G; v->node->distance = u->node->distance + 1; v->node->parent = u->node; // printf("v= %d, v parent shi =%d v distance is %d\n", v->node->key, v->node->parent->key, v->node->distance); ENQUEUE(Q, v->node); } u->node->Adj->front = u->node->Adj->front->next; } u->node->c = B; } } int main() { link All_Point=(link)malloc(sizeof(l)); //這個連結串列裡面存著所有的結點 point p1, p2, p3, p4, p5; All_Point=INI_LINK(All_Point); p1 = INI_POINT(12); p2 = INI_POINT(18); p3 = INI_POINT(22); p4 = INI_POINT(31); p5 = INI_POINT(44); p1 = INI_SOURCE_POINT(p1); //p1 is a source point CONNECTION(p1, p2); CONNECTION(p1, p3); CONNECTION(p3, p4); CONNECTION(p3, p5); INSERT_LINK(All_Point, p1); INSERT_LINK(All_Point, p2); INSERT_LINK(All_Point, p3); INSERT_LINK(All_Point, p4); INSERT_LINK(All_Point, p5); printf("the result is:\n"); BFS(All_Point, p1); return 0; }

在這裡插入圖片描述
我連線的是這樣一個圖,結果顯示的是結點和對應的距離

          18--------------------12(源節點)
                                |
                                |
                                |
                                |
                                22  -----------------31
                                |
                                |
                                |
                                44