圖的遍歷--深度優(yōu)先搜索算法枫攀,廣度優(yōu)先搜索算法

1 深度優(yōu)先搜索算法

深度優(yōu)先搜索(Depth First Search)遍歷類似于樹的先序遍歷赖捌,是樹的先序遍歷的推廣。
采用的數(shù)據(jù)結構是(正)鄰接鏈表西采。

算法思想:
設初始狀態(tài)時圖中所有頂點未被訪問,則:
(1):從圖中某個頂點v_i出發(fā)鞠柄,訪問v_i;然后找到v_i的一個鄰接頂點v_{i1}侦高;
(2):從v_{i1}出發(fā),深度優(yōu)先搜索訪問和v_{i1}相鄰接且未被訪問的所有頂點厌杜。
(3):轉(1)矫膨,直到和v_i相鄰接的所有頂點都被訪問為止;
(4):繼續(xù)選取圖中未被訪問的頂點v_j作為起始頂點期奔,轉(1)侧馅,直到圖中所有頂點都被訪問為止。

算法實現(xiàn):
由算法思想知呐萌,這是一個遞歸的過程馁痴。因此先設計一個從某個頂點為v_0開始深度優(yōu)先搜索的函數(shù),便于調用肺孤。
在遍歷整個圖時罗晕,可以對圖中每一個未訪問的頂點執(zhí)行所定義的函數(shù)。
定義一個全局變量赠堵,記錄每個結點是否訪問過小渊,初始為FALSE。

#include <stdio.h>
#include <stdlib.h>

#define MAX_VEX 30
typedef enum {
    DG, AG, WDG, WAG
} GraphKind;

typedef struct LinkNode {
    int adjvex;//鄰接點在頭結點數(shù)組中的位置(下標)
    int info;// 與邊或弧相關的信息, 如權值
    struct LinkNode *nextarc;//指向下一個表結點
} LinkNode;/*表結點類型定義 */

typedef struct VexNode {
    char data; // 頂點信息
    LinkNode *firstarc; // 指向第一個表結點
} VexNode;/* 頂點結點類型定義 */

typedef struct {
    GraphKind kind;/*圖的種類標志 */
    int vexnum;//頂點數(shù)
    VexNode AdjList[MAX_VEX];//鄰接表
} ALGraph;/* 圖的結構定義 */

int visited[MAX_VEX];//0未訪問茫叭,1已訪問

void DFS(ALGraph *G, int v) {
    LinkNode *p = G->AdjList[v].firstarc;//鏈表的第一個結點
    visited[v] = 1;//設置已訪問標志
    visit(v);//訪問頂點v
    while (p != NULL) {
        if (visited[p->adjvex] == 0) {//未訪問
            DFS(G, p->adjvex);
        }
        p = p->nextarc;//從v未訪問過的鄰接頂點出發(fā)深度優(yōu)先搜索
    }

}

void DFS_traverse_Graph(ALGraph *G) {//深度優(yōu)先搜索主函數(shù)
    for (int i = 0; i < G->vexnum; i++) {//訪問標志初始化
        visited[i] = 0;
    }
    for (int i = 0; i < G->vexnum; i++) {
        if (visited[i]) {
            DFS(G, i);
        }
    }
}

算法分析:
遍歷時酬屉,對圖的每個頂點至多調用一次DFS函數(shù)。
其實質就是對每個頂點查找鄰接頂點的過程揍愁,取決于存儲結構呐萨。
當圖有e條邊,其時間復雜度為O(e),總時間復雜度為O(n+e)莽囤。

2 廣度優(yōu)先搜索算法

廣度優(yōu)先搜索(Breadth First Search) 遍歷類似于樹的按層次遍歷的過程谬擦。

算法思想:
設初始狀態(tài)圖中的所有頂點未被訪問,則
(1)從圖中某個頂點v_i出發(fā)朽缎,訪問v_i惨远;
(2)訪問v_i的所有相鄰接且未被訪問的所有頂點v_{i1},v_{i2},\cdots,v_{im}
(3)以v_{i1},v_{i2},\cdots,v_{im}的次序话肖,以v_j(1\leq j\leq m)依次作為v_i北秽,轉(1);
(4)繼續(xù)選取圖中未被訪問頂點v_k作為起始頂點狼牺,轉(1)羡儿,直到圖中所有頂點都被訪問為止。

算法實現(xiàn):
為了標記圖中頂點是否被訪問過是钥,同樣需要一個訪問標記數(shù)組掠归;其次缅叠,為了依次訪問與v_i相鄰接的各個頂點,需要附加一個隊列來保存訪問v_i的相鄰接的頂點虏冻。

#include <stdio.h>
#include <stdlib.h>

#define MAX_VEX 30

int visited[MAX_VEX];

typedef struct Queue {
    int elem[MAX_VEX];
    int front, rear;
} Queue;//定義一個隊列保存將要訪問的頂點

typedef enum {
    DG, AG, WDG, WAG//有向圖肤粱,無向圖,帶權有向圖厨相,帶權無向圖
} GraphKind;

typedef struct LinkNode {
    int adjvex;//鄰接點在頭結點數(shù)組中的位置(下標)
    int info;// 與邊或弧相關的信息, 如權值
    struct LinkNode *nextarc;//指向下一個表結點
} LinkNode;/*表結點類型定義 */

typedef struct VexNode {
    char data; // 頂點信息
    LinkNode *firstarc; // 指向第一個表結點
} VexNode;/* 頂點結點類型定義 */

typedef struct {
    GraphKind kind;/*圖的種類標志 */
    int vexnum;//頂點數(shù)
    VexNode AdjList[MAX_VEX];//鄰接表
} ALGraph;/* 圖的結構定義 */

void visit(char c) {
    printf("%c ", c);
}

void BFS_traverse_graph(ALGraph *G) {
    int w;
    LinkNode *node;
    Queue *queue = (Queue *) malloc(sizeof(Queue));
    queue->front = queue->rear = 0;//建立空隊列并初始化
    for (int i = 0; i < G->vexnum; i++) {
        visited[i] = 0;//訪問標志初始化
    }
    for (int i = 0; i < G->vexnum; i++) {//非連通圖需要循環(huán)每個結點
        if (visited[i] == 0) {//沒有訪問過
            queue->elem[++queue->rear] = i;//i入隊
            while (queue->front != queue->rear) {//隊不空一直循環(huán)
                w = queue->elem[++queue->front];//出隊
                visited[w] = 1;//置訪問標志
                visit(G->AdjList[w].data);//進行訪問
                node = G->AdjList[w].firstarc;
                while (node != NULL) {
                    if (visited[node->adjvex] == 0) {
                        queue->elem[++queue->rear] = node->adjvex;
                    }
                    node = node->nextarc;
                }
            }
        }
    }
}

ALGraph *createGraph() {
    ALGraph *G = (ALGraph *) malloc(sizeof(ALGraph));
    printf("圖的種類標識:\n");
    scanf("%d", &G->kind);
    G->vexnum = 0;
    return G;
}

int locateVex(ALGraph *G, char ch) {
    for (int i = 0; i < G->vexnum; i++) {
        if (G->AdjList[i].data == ch) {
            return (i);
        }
    }
    return (-1);/* 圖中無此頂點*/
}

int addVex(ALGraph *G, char ch) {
    int k;
    if (G->vexnum >= MAX_VEX) {
        printf("Vertex Overflow !\n");
        return (-1);
    }
    if (locateVex(G, ch) != -1) {
        printf("Vertex has existed !\n");
        return (-1);
    }
    G->AdjList[G->vexnum].data = ch;
    G->AdjList[G->vexnum].firstarc = NULL;
    k = ++G->vexnum;
    return k;
}

int addArc(ALGraph *G, char ch1, char ch2, int weight) {
    int k = locateVex(G, ch1);
    int j = locateVex(G, ch2);
    if (k == -1 || j == -1) {
        printf("Arc’s Vertex do not exist!\n");
        return (-1);
    }
    LinkNode *p = (LinkNode *) malloc(sizeof(LinkNode));
    p->adjvex = k;
    p->info = weight;
    LinkNode *q = (LinkNode *) malloc(sizeof(LinkNode));
    p->adjvex = j;
    q->info = weight;
    if (G->kind == AG || G->kind == WAG) {//無向圖领曼,用頭插入法插入到兩個單鏈表
        p->nextarc = G->AdjList[k].firstarc;
        G->AdjList[k].firstarc = p;
        q->nextarc = G->AdjList[j].firstarc;
        G->AdjList[j].firstarc = q;
    } else {
        p->nextarc = G->AdjList[k].firstarc;
        G->AdjList[k].firstarc = p;   /*建立正鄰接鏈表用 */

//        q->nextarc = G->AdjList[j].firstarc;
//        G->AdjList[j].firstarc = q;/*建立逆鄰接鏈表用 */
    }
}

int main() {
    ALGraph *G = createGraph();
    addVex(G, 'a');
    addVex(G, 'b');
    addVex(G, 'c');
    addVex(G, 'd');
    addVex(G, 'e');
    addArc(G, 'a', 'b', 0);
    addArc(G, 'a', 'd', 0);
    addArc(G, 'b', 'c', 0);
    addArc(G, 'd', 'e', 0);
    addArc(G, 'c', 'e', 0);
    BFS_traverse_graph(G);
}

用廣度優(yōu)先搜索算法遍歷圖與深度優(yōu)先搜索算法遍歷圖的唯一區(qū)別是鄰接點搜索次序不同。
廣度優(yōu)先搜索算法遍歷圖的總時間復雜度是O(n+e)蛮穿。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末庶骄,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子践磅,更是在濱河造成了極大的恐慌单刁,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,542評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件府适,死亡現(xiàn)場離奇詭異羔飞,居然都是意外死亡,警方通過查閱死者的電腦和手機檐春,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,596評論 3 385
  • 文/潘曉璐 我一進店門逻淌,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人疟暖,你說我怎么就攤上這事卡儒。” “怎么了誓篱?”我有些...
    開封第一講書人閱讀 158,021評論 0 348
  • 文/不壞的土叔 我叫張陵朋贬,是天一觀的道長。 經(jīng)常有香客問我窜骄,道長,這世上最難降的妖魔是什么摆屯? 我笑而不...
    開封第一講書人閱讀 56,682評論 1 284
  • 正文 為了忘掉前任邻遏,我火速辦了婚禮,結果婚禮上虐骑,老公的妹妹穿的比我還像新娘准验。我一直安慰自己,他們只是感情好廷没,可當我...
    茶點故事閱讀 65,792評論 6 386
  • 文/花漫 我一把揭開白布糊饱。 她就那樣靜靜地躺著,像睡著了一般颠黎。 火紅的嫁衣襯著肌膚如雪另锋。 梳的紋絲不亂的頭發(fā)上滞项,一...
    開封第一講書人閱讀 49,985評論 1 291
  • 那天,我揣著相機與錄音夭坪,去河邊找鬼文判。 笑死,一個胖子當著我的面吹牛室梅,可吹牛的內容都是我干的戏仓。 我是一名探鬼主播,決...
    沈念sama閱讀 39,107評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼亡鼠,長吁一口氣:“原來是場噩夢啊……” “哼赏殃!你這毒婦竟也來了?” 一聲冷哼從身側響起间涵,我...
    開封第一講書人閱讀 37,845評論 0 268
  • 序言:老撾萬榮一對情侶失蹤嗓奢,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后浑厚,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體股耽,經(jīng)...
    沈念sama閱讀 44,299評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,612評論 2 327
  • 正文 我和宋清朗相戀三年钳幅,在試婚紗的時候發(fā)現(xiàn)自己被綠了物蝙。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,747評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡敢艰,死狀恐怖诬乞,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情钠导,我是刑警寧澤震嫉,帶...
    沈念sama閱讀 34,441評論 4 333
  • 正文 年R本政府宣布,位于F島的核電站牡属,受9級特大地震影響票堵,放射性物質發(fā)生泄漏。R本人自食惡果不足惜逮栅,卻給世界環(huán)境...
    茶點故事閱讀 40,072評論 3 317
  • 文/蒙蒙 一悴势、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧措伐,春花似錦特纤、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,828評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春昔穴,著一層夾襖步出監(jiān)牢的瞬間镰官,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,069評論 1 267
  • 我被黑心中介騙來泰國打工傻咖, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留朋魔,地道東北人。 一個月前我還...
    沈念sama閱讀 46,545評論 2 362
  • 正文 我出身青樓卿操,卻偏偏與公主長得像警检,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子害淤,可洞房花燭夜當晚...
    茶點故事閱讀 43,658評論 2 350

推薦閱讀更多精彩內容