有向圖鄰接矩陣深度優先搜尋
阿新 • • 發佈:2018-11-17
上一個文章是寫的無向圖和鄰接連結串列的廣度搜索,深度搜索就用矩陣和有向圖了。
矩陣處理起來還是會比連結串列簡單一些。
先分析資料結構:
1.儲存所有結點的集合用到了一個單向迴圈連結串列,為什麼要用迴圈連結串列呢,因為在儲存結點資料的時候是按照輸入資料的順序來儲存的,如果是用一個數組或者單向連結串列,我們可以得到陣列或連結串列第一個元素作為源節點的遍歷,但是我要是指定陣列中的第三個元素作為源節點呢。這樣就不太好操作了,所以用了一個迴圈的連結串列,先把指標移到指定的任意一個源節點作為表頭再繼續操作。
其他的就是普通的二維陣列結構體等沒什麼特別的了。
注意:
結點的輸入順序還是得記一個位置,因為二維陣列是按那個順序建立的,有一個position可以把二維陣列和連結串列一一對應起來。
其實很難一次性不出問題,我一般第一次執行都是得不到結果或者只得到部分結果。但是隻要會除錯,其他的都不是什麼問題了,特別是main函式是一個一個處理的,每個函式都是一次一次呼叫的,在除錯的時候哪裡出問題了會很明顯。
還有就是最近發現的一個小skill,在定義結構體的時候可以把key啊這類的明顯的不同的變數先定義,在除錯的時候就能先顯示看到它。
下面程式碼看函式名基本就知道是在幹嘛,註釋寫的有點少將就看一下。
#include "stdafx.h"
#include<stdio.h>
#include<stdlib.h>
#define N 6 //plane to create a 6*6 matrix
int time; //the whole proccess's time
int n = 0;
typedef enum Color{ W, G, B }Color;
typedef struct vertex_ *vertex;
typedef struct vertex_
{
int key;
int d; //start time
int f; //final time
int position; //store the position of this vertex, position .position is determined by input sentence
Color c;
vertex parent;
}v;
typedef struct list_ *list;
typedef struct list_ //建立一個單向迴圈連結串列
{
vertex v;
list next;
// int position; //to correspond this position with metrix
}l;
void DFS_VISIT(int a[][N], list head, vertex x);
void DFS(int a[][N], vertex b[]);
vertex INI_VERTEX(int key)
{
vertex x = (vertex)malloc(sizeof(v));
x->key = key;
x->d = 0;
x->f = 0;
x->position = n;
x->parent = NULL;
x->c = W;
n++;
return x;
}
void INI_METRIX(int a[][N])
{
for (int i = 0; i < N; i++)
for (int j = 0; j < N; j++)
a[i][j] = 0;
}
list INI_LIST(list x)
{
x = (list)malloc(sizeof(l));
x = NULL;
return x;
// x->next = NULL;
// x->v = NULL;
}
void CONNECTION(int a[][N],vertex out, vertex in)
{
a[out->position][in->position] = 1;
}
list MOVE_HEAD(list head, vertex x)
{
list p = (list)malloc(sizeof(l));
p = head;
if (head->v->position == x->position)
{
return head;
}
else
{
p = p->next;
while (p != head)
{
if (p->v->position == x->position)
return p;
p = p->next;
}
}
}
void DFS(int a[][N],list head)
{
list p = head;
while(p->next!=head) //迴圈一圈
{
if (p->v->c == W)
DFS_VISIT(a, head, p->v);
p=p->next;
}
if (p->v->c == W)
DFS_VISIT(a, head, p->v);
}
void DFS_VISIT(int a[][N], list head, vertex x)
{
time = time++;
x->d = time;
x->c = G;
for (int i = 0; i<N; i++)
if (a[x->position][i] == 1 )
{
list p = head;
while (p->next != head) //迴圈一圈
{
if (p->v->position == i && p->v->c == W)
{
p->v->parent = x;
DFS_VISIT(a,head, p->v);
}
p=p->next;
}
//97行p->next了,在檢查while的時候還要next,就會導致連結串列的最後一個元素無法進行處理,所以最後追加一個對最後一個元素的處理,下面還有兩個類似的處理
//個人感覺比起先判斷p==head的程式碼量要少那麼一點點。
if (p->v->position == i && p->v->c == W)
{
p->v->parent = x;
DFS_VISIT(a, head, p->v);
}
}
x->c = B;
time = time + 1;
x->f = time;
}
list INSERT_VERTEX(list head, vertex x)
{
list new_p = (list)malloc(sizeof(l));
new_p->next = NULL;
new_p->v = x;
// new_p->position = n;
// n++;
if (head == NULL)
{
head = new_p;
head->next = head;
}
else
{
list p = head; //遍歷傳進來這個連結串列,看他是什麼情況
while (p->next != head)
{
p = p->next;
} //遍歷一遍,找到新節點插入的位置,
p->next = new_p;
new_p->next = head;
}
return head;
}
int main()
{
int a[N][N];
list b = (list)malloc(sizeof(l));
vertex p1, p2, p3, p4, p5, p6;
INI_METRIX(a);
b=INI_LIST(b);
p1=INI_VERTEX(8);
p2=INI_VERTEX(3);
p3=INI_VERTEX(6);
p4=INI_VERTEX(7);
p5=INI_VERTEX(5);
p6=INI_VERTEX(10);
b=INSERT_VERTEX(b, p1);
b=INSERT_VERTEX(b, p2);
b=INSERT_VERTEX(b, p3);
b=INSERT_VERTEX(b, p4);
b=INSERT_VERTEX(b, p5);
b=INSERT_VERTEX(b, p6);
CONNECTION(a, p1, p2);
CONNECTION(a, p1, p3);
CONNECTION(a, p2, p3);
CONNECTION(a, p3, p4);
CONNECTION(a, p4, p2);
CONNECTION(a, p5, p4);
CONNECTION(a, p5, p6);
CONNECTION(a, p6, p6);
printf("當頭指標是p3,(key=6)時\n");
b=MOVE_HEAD(b, p3);
DFS(a, b);
list p=b;
while (p->next != b)
{
printf("(%d, d=%d,f=%d)\n", p->v->key, p->v->d, p->v->f);
p = p->next;
}
printf("(%d, d=%d,f=%d)\n", p->v->key, p->v->d, p->v->f);
return 0;
}