無向圖鄰接連結串列的廣度優先搜尋
阿新 • • 發佈:2018-11-17
個人認為圖的演算法看起來非常簡潔,但是實現起來需要基礎很紮實。因為經常會涉及多種簡單的資料結構,怎樣把他們恰當的串聯起來,不會報那種,空指標了,型別不匹配,實體型別不符合了等等。
在做無向圖鄰接連結串列廣度優先搜尋的時候,寫的很冒火,想去找別的博主的程式碼借鑑一下,發現大部分,真的是大部分,都是有問題的,有些甚至都執行不出來。於是硬著頭皮自己寫了。
第一步是分析:
無向圖裡面用到的資料結構一個是連結串列,這裡用到了兩次。一個連結串列用於存放每個元素的與之相連的元素,用了一個鄰接連結串列。還要考慮所有元素怎麼連成一張圖,前面的連結串列可以得到的散開的這種形式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