1. 程式人生 > >有向圖鄰接矩陣深度優先搜尋

有向圖鄰接矩陣深度優先搜尋

上一個文章是寫的無向圖和鄰接連結串列的廣度搜索,深度搜索就用矩陣和有向圖了。
矩陣處理起來還是會比連結串列簡單一些。

先分析資料結構:
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; }

在這裡插入圖片描述

在這裡插入圖片描述