目錄
成都創(chuàng)新互聯(lián)是一家專注于網(wǎng)站建設(shè)、成都網(wǎng)站設(shè)計(jì)與策劃設(shè)計(jì),柳江網(wǎng)站建設(shè)哪家好?成都創(chuàng)新互聯(lián)做網(wǎng)站,專注于網(wǎng)站建設(shè)十年,網(wǎng)設(shè)計(jì)領(lǐng)域的專業(yè)建站公司;建站業(yè)務(wù)涵蓋:柳江等地區(qū)。柳江做網(wǎng)站價(jià)格咨詢:028-86922220→?圖的遍歷
→?深度優(yōu)先搜索遍歷
↓?基本思想:
↓ →?遞歸深度優(yōu)先搜索遍歷
↓? ? 算法思想:
↓ →非遞歸深度優(yōu)先搜索遍歷
↓? 算法思想:
→??廣度優(yōu)先搜索遍歷
↓??基本思想:
→??算法實(shí)現(xiàn)的綜合應(yīng)用:(無向圖為例)? ? ? ? ? ? ?? ? ? ? ? ? ? ? ? ?
↓?運(yùn)行結(jié)果:
↓?算法實(shí)現(xiàn):
↓? →?算法實(shí)現(xiàn)過程中的注意點(diǎn)及解決方法:
↓? 注意點(diǎn)一:
↓? 解決方法:
↓? 注意點(diǎn)二:
↓? 解決方法:
??圖的遍歷是從圖中某個(gè)頂點(diǎn)出發(fā),訪遍圖中其余頂點(diǎn),且都訪問一次的過程。
? 圖與樹類似,不同的是圖的每個(gè)頂點(diǎn)都有可能與其余所有頂點(diǎn)鄰接,為避免重復(fù)訪問同一個(gè)頂點(diǎn),在遍歷的過程中應(yīng)標(biāo)記該頂點(diǎn)訪問過。
思考:
對(duì)于圖中有回路,對(duì)于連通圖,如何實(shí)現(xiàn)遍歷只訪問每個(gè)頂點(diǎn)一次,也就是遇到回退的情況或圖中頂點(diǎn)都已完成訪問時(shí)如何確保不會(huì)再次訪問頂點(diǎn)?
設(shè)置一個(gè)標(biāo)志數(shù)組 Visited【】實(shí)現(xiàn),此數(shù)組用于標(biāo)記所有頂點(diǎn)是否訪問過,初始值為0,如果訪問過,更新此頂點(diǎn)的標(biāo)志為1,這樣遇到上述情況時(shí),判斷頂點(diǎn)的標(biāo)志數(shù)組是否為1即可解決。
圖的遍歷方法有:深度優(yōu)先搜索遍歷和廣度優(yōu)先搜索遍歷,兩種遍歷方法對(duì)無向圖,有向圖都適用。通過圖的遍歷可以知道圖是否為連通圖。
深度優(yōu)先搜索遍歷和二叉樹的先序遍歷類似,盡可能先對(duì)縱深方向進(jìn)行搜索。
基本思想:? 先從圖的某個(gè)頂點(diǎn) V0 出發(fā),訪問頂點(diǎn),然后依次從V0 各個(gè)未訪問的鄰接點(diǎn)出發(fā)深度優(yōu)先搜索遍歷,直到所有和 V0 相通的頂點(diǎn)都被訪問到。如果是非連通圖,上述操作結(jié)束后,需要再選另一個(gè)圖中未被訪問的頂點(diǎn)作為新的出發(fā)點(diǎn),重復(fù)上述操作。
?
?深度優(yōu)先搜索遍歷的結(jié)果為:A B D F C G E H I 。
一個(gè)頂點(diǎn)可能會(huì)有多個(gè)鄰接點(diǎn),訪問次序不同,所以圖的遍歷的序列不唯一。
對(duì)于鄰接矩陣存儲(chǔ)結(jié)構(gòu)的圖,適合稠密圖 ,遍歷時(shí),需要檢查n^2個(gè)元素,時(shí)間復(fù)雜度為O(n^2)。
鄰接表存儲(chǔ)結(jié)構(gòu)的圖,適合稀疏圖,找鄰接點(diǎn)只需在邊表中所有邊結(jié)點(diǎn)檢查一遍,時(shí)間為O(e),時(shí)間復(fù)雜度為O(n+e)。
?采用遞歸的方式遍歷,如果訪問到頂點(diǎn)A1,根據(jù)判斷條件知其沒有鄰接點(diǎn)(無法深度優(yōu)先搜索遍歷),需要回退到上一個(gè)頂點(diǎn)A,繼續(xù)查找A的其余鄰接點(diǎn)A2,,,
算法思想:?從一個(gè)頂點(diǎn)v出發(fā)
1、訪問頂點(diǎn),標(biāo)記此頂點(diǎn)訪問過
2、從鄰接矩陣中找到頂點(diǎn)位置,依次選擇其鄰接點(diǎn)且并判斷是否訪問過,進(jìn)行深度遍歷。
遍歷偽代碼:
void DFS(Graph g,int v0) { visit(vo); //訪問頂點(diǎn) visited[v0]=1; //標(biāo)記訪問過頂點(diǎn) w=FirstAdjVex(g,vo); //查找vo的第一個(gè)鄰接點(diǎn) while(w!=-1) // 鄰接點(diǎn)存在 { if(!visited[w]) //鄰接點(diǎn)未訪問過 DFS(g,w); w=NextAdjVex(g,vo,w); // vo的下一個(gè)鄰接點(diǎn) } } void TraverseG(Graph g) { for(v=0;v
二叉樹遍歷時(shí)已經(jīng)知道,對(duì)于遞歸遍歷可以通過棧轉(zhuǎn)化為非遞歸遍歷的形式。
? 算法思想:1、棧初始化
2、訪問頂點(diǎn),標(biāo)記訪問過,該頂點(diǎn)入棧
3、當(dāng)棧不為空時(shí):
1 、取棧頂頂點(diǎn)的位置,存在未被訪問的鄰接點(diǎn)w
2、訪問頂點(diǎn)w,標(biāo)記訪問,w頂點(diǎn)入棧(便于查找w頂點(diǎn)的其他鄰接點(diǎn))然后在棧不為空的條件下重復(fù)上述操作。
3、否則,當(dāng)前頂點(diǎn)出棧,(表明頂點(diǎn)的鄰接點(diǎn)都訪問過,或該棧頂頂點(diǎn)沒有鄰接點(diǎn),出棧,繼續(xù)尋找現(xiàn)在棧頂頂點(diǎn)的鄰接點(diǎn))。
基本思想:?廣度優(yōu)先搜索遍歷與二叉樹的層次遍歷類似,從某個(gè)頂點(diǎn)出發(fā)開始訪問,先訪問該頂點(diǎn)的所有鄰接點(diǎn),然后根據(jù)其鄰接點(diǎn)的訪問順序再訪問各自的所有鄰接點(diǎn),直到所有與頂點(diǎn)路徑相通的頂點(diǎn)都被訪問到。圖中若有未被訪問到,另選該頂點(diǎn)作為出發(fā)點(diǎn)。
廣度優(yōu)先搜索遍歷的結(jié)果為:A B C D E F G H I 。
算法思想:
? 根據(jù)隊(duì)列的特點(diǎn),先進(jìn)先出,訪問頂點(diǎn)時(shí)入隊(duì),并標(biāo)記訪問過,然后出隊(duì),隊(duì)頭元素出隊(duì)時(shí),依次將其未被訪問到的頂點(diǎn)訪問并入隊(duì),每個(gè)頂點(diǎn)都入隊(duì)一次。
? 從V0頂點(diǎn)出發(fā)
? 1、隊(duì)初始化
? 2、訪問V0頂點(diǎn),標(biāo)記訪問過,并入隊(duì)
? 3、當(dāng)隊(duì)不為空時(shí):
? 出隊(duì);
? 將出隊(duì)的頂點(diǎn)所有未被訪問過的頂點(diǎn)訪問,標(biāo)記并入隊(duì)。
??
?
#include
#include #define MAXVEX 20 typedef struct { int arcs[MAXVEX][MAXVEX]; char vex[MAXVEX]; int vexnum; int arcnum; }AdjMatrix; //對(duì)圖的頂點(diǎn)初始化 AdjMatrix* Init() { AdjMatrix* G = (AdjMatrix*)malloc(sizeof(AdjMatrix)); if (G == NULL) printf("申請(qǐng)內(nèi)存錯(cuò)誤"); for (int i = 0; i arcs[i][j] = 0; } for (int i = 0; i< MAXVEX; i++) G->vex[i] = 0; G->vexnum = 0; G->arcnum = 0; return G; } //=================================== 鄰接矩陣存儲(chǔ)結(jié)構(gòu)創(chuàng)建圖 ========================= //查找匹配的頂點(diǎn)在矩陣中的位置 int LocateVex(AdjMatrix* G, char v) { int i; for (i = 1; i<= G->vexnum; i++) { if (G->vex[i] == v) return i; } return 0; } AdjMatrix* Create() { AdjMatrix* G=Init(); int i, j, k; char vex1, vex2; printf("----輸入圖的頂點(diǎn)數(shù)與邊數(shù)-----\n"); scanf("%d%d", &G->vexnum, &G->arcnum); printf("-----依次輸入圖中%d個(gè)頂點(diǎn)------\n", G->vexnum); for (i = 1; i<=G->vexnum; i++) { scanf(" %c",&(G->vex[i])); //注意點(diǎn)一: } printf("-----輸入圖中%d條邊-----\n", G->arcnum); for (k = 1; k<= G->arcnum; k++) { printf("第%d條邊:\n ", k); scanf(" %c", &vex1); scanf(" %c", &vex2); i = LocateVex(G, vex1); j = LocateVex(G, vex2); G->arcs[i][j] = 1; G->arcs[j][i] = 1; } printf("=================》鄰接矩陣建立圖完成 ================《\n"); return G; } //==================================== 鄰接矩陣遞歸深度搜索遍歷 ====================== void DFS(AdjMatrix*G, int v) { int i = 0; static int visited[20]; //注意點(diǎn)二: printf("%c ", G->vex[v]); visited[v] = 1; for (i = 1; i<= G->vexnum; i++) { if (G->arcs[v][i] != 0 && visited[i] != 1) DFS(G, i); } } //======================================== 棧 ======================================= //定義結(jié)點(diǎn)結(jié)構(gòu) typedef struct Node { char data; struct Node* next; }Slstacktype; //初始化棧頭指針 Slstacktype* Initstack() { Slstacktype* top = (Slstacktype*)malloc(sizeof(Slstacktype)); top->next = NULL; return top; } //進(jìn)棧 Slstacktype* Push(Slstacktype* top,char vex) { Slstacktype* p=(Slstacktype*)malloc(sizeof(Slstacktype)); if (p == NULL) return NULL; p->data = vex; p->next = top->next; top->next = p; return top; } //出棧 Slstacktype* Pop(Slstacktype* top) { Slstacktype* q; if (top->next == NULL) //判斷棧是否為空 return NULL; q = top->next; top->next = q->next; free(q); return top; } //=================================== 非遞歸鄰接矩陣存儲(chǔ)結(jié)構(gòu)的深度搜索遍歷 ============= //取棧頂頂點(diǎn)的位置 int include_stack(AdjMatrix* G, Slstacktype* top) { int i; for (i = 1; i<= G->vexnum; i++) { if (G->vex[i] == top->next->data) return i; } return 0; } void DFS_stack(AdjMatrix*G,int v) { int i; Slstacktype* top = Initstack(); //棧的初始化 static int visited[20]; //定義靜態(tài)的標(biāo)志數(shù)組 printf("%c ", G->vex[v]); visited[v] = 1; Push(top, G->vex[v]); while (top->next != NULL) { v = include_stack(G, top); for (i = 1; i<= G->vexnum; i++) { if (G->arcs[v][i] != 0 && visited[i] != 1) { printf("%c ", G->vex[i]); visited[i] = 1; Push(top, G->vex[i]); break; } } if (i >G->vexnum) //頂點(diǎn)的鄰接點(diǎn)都訪問過,或沒有鄰接點(diǎn)時(shí)退棧頂結(jié)點(diǎn) { top = Pop(top); } } } //=========================================== 隊(duì)列 ====================================== typedef struct Node2 { char data; struct Node2* next; }QNode; typedef struct { QNode* front; QNode* rear; }LQNode; //隊(duì)的初始化 LQNode* Init_Q() { LQNode* p = (LQNode*)malloc(sizeof(LQNode)); QNode* q = (QNode*)malloc(sizeof(QNode)); p->front = p->rear = q; q->next = NULL; return p; } //入隊(duì) void Push_Q(LQNode* p, char vex) { QNode* q = (QNode*)malloc(sizeof(QNode)); if (q == NULL) printf("申請(qǐng)空間錯(cuò)誤"); q->data = vex; q->next = NULL; p->rear->next = q; p->rear = q; } //出隊(duì) char Pop_Q(LQNode* p) { char vex; QNode* q; if (p->front == p->rear) return ; q = p->front->next; p->front->next = q->next; vex = q->data; if (p->front->next == NULL) p->rear = p->front; free(q); return vex; } //========================================== 鄰接矩陣的廣度優(yōu)先搜素遍歷 ==================== int include_Q(AdjMatrix* G, char vex) //取出隊(duì)頂點(diǎn)在鄰接矩陣中的位置 { for (int i = 1; i<= G->vexnum; i++) { if (G->vex[i] == vex) return i; } return 0; } void BFS(AdjMatrix* G, int v) { static visited[20]; LQNode* p = Init_Q(); printf("%c ", G->vex[v]); visited[v] = 1; Push_Q(p, G->vex[v]); while (p->front->next!=NULL) { int i; v = include_Q(G,Pop_Q(p)); for (i = 1; i<= G->vexnum; i++) { if (G->arcs[v][i] != 0 && visited[i] != 1) { printf("%c ", G->vex[i]); visited[i] = 1; Push_Q(p, G->vex[i]); } } } } //======================================== 打印鄰接矩陣 ============================== void print(AdjMatrix* G) { for (int i = 1; i<= G->vexnum; i++) { for (int j = 1; j<= G->vexnum; j++) { printf("%d ", G->arcs[i][j]); } printf("\n"); } } main() { int v; printf("==============》 鄰接矩陣存儲(chǔ)結(jié)構(gòu)創(chuàng)建圖 《===========\n"); AdjMatrix* G = Create(); printf("==============》 打印鄰接矩陣 《============\n"); print(G); printf("\n"); printf("----輸入遍歷起始位置-----\n"); scanf("%d", &v); printf("==============》 遞歸 深度搜索遍歷 《========== \n"); DFS(G, v); printf("\n"); printf("==============》 非遞歸 深度搜索遍歷 《========== \n"); DFS_stack(G, v); printf("\n"); printf("==============》 廣度優(yōu)先搜索遍歷 《==============\n "); BFS(G, v); printf("\n"); }
注意點(diǎn)一:再多次用scanf()函數(shù)輸入值時(shí),輸入的是字符類型的值時(shí),需要考慮scanf函數(shù)的問題
? 解決方法:可以在 %c前面空格用于接收留在緩沖區(qū)中的空格、回車等符號(hào)
注意點(diǎn)二:?定義的標(biāo)志數(shù)組,需要初始化為0,每次訪問過后需要更新為1,然而在遞歸函數(shù)中,每一次調(diào)用都會(huì)重新初始化數(shù)組,然后就會(huì)造成死循環(huán)的情況(可以試試寫寫,印象更深)。
解決方法:可以定義一個(gè)大一點(diǎn)的數(shù)組,利用靜態(tài)數(shù)組未初始化就會(huì)給所有的數(shù)組元素賦初值0,就很好的解決這個(gè)問題。
?靜態(tài)數(shù)組:靜態(tài)數(shù)組的長(zhǎng)度是預(yù)先定義好的,在整個(gè)程序中,一旦給定大小后就無法改變。 靜態(tài)數(shù)組在內(nèi)存中位于棧區(qū),是在定義時(shí)就已經(jīng)在棧上分配了固定大小,在運(yùn)行時(shí)這個(gè)大小不能改變,在函數(shù)執(zhí)行完以后,系統(tǒng)自動(dòng)銷毀; 如:int a[10]; 雖然c語(yǔ)言規(guī)定,只有靜態(tài)存儲(chǔ)的數(shù)組才能初始化,但一般的c編譯系統(tǒng)都允許對(duì)動(dòng)態(tài)存儲(chǔ)的數(shù)組賦初值。靜態(tài)存儲(chǔ)的數(shù)組如果沒有初始化,系統(tǒng)自動(dòng)給所有的數(shù)組元素賦0。
你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機(jī)房具備T級(jí)流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級(jí)服務(wù)器適合批量采購(gòu),新人活動(dòng)首月15元起,快前往官網(wǎng)查看詳情吧
分享題目:圖(二)——圖的遍歷-創(chuàng)新互聯(lián)
轉(zhuǎn)載來源:http://muchs.cn/article30/dhgppo.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供服務(wù)器托管、網(wǎng)站維護(hù)、營(yíng)銷型網(wǎng)站建設(shè)、搜索引擎優(yōu)化、移動(dòng)網(wǎng)站建設(shè)、網(wǎng)站建設(shè)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容