圖的儲存結構及遍歷演算法
一、圖的儲存結構
1.1 鄰接矩陣
圖的鄰接矩陣儲存方式是用兩個陣列來表示圖。一個一維陣列儲存圖中頂點資訊,一個二維陣列(鄰接矩陣)儲存圖中的邊或弧的資訊。
設圖G有n個頂點,則鄰接矩陣是一個n*n的方陣,定義為:
看一個例項,下圖左就是一個無向圖。
從上面可以看出,無向圖的邊陣列是一個對稱矩陣。
從這個矩陣中,很容易知道圖中的資訊。
(1)要判斷任意兩頂點是否有邊無邊就很容易了;
(2)要知道某個頂點的度,其實就是這個頂點vi在鄰接矩陣中第i行或(第i列)的元素之和;
(3)求頂點vi的所有鄰接點就是將矩陣中第i行元素掃描一遍,arc[i][j]為1就是鄰接點;
而有向圖講究入度和出度,頂點vi的入度為1,正好是第i列各數之和。頂點vi的出度為2,即第i行的各數之和。
若圖G是網圖,有n個頂點,則鄰接矩陣是一個n*n的方陣,定義為:
這裡的Wij表示(vi,vj)上的權值。無窮大表示一個計算機允許的、大於所有邊上權值的值,也就是一個不可能的極限值。下面左圖就是一個有向網圖,右圖就是它的鄰接矩陣。
那麼鄰接矩陣是如何實現圖的建立的呢?程式碼如下:
#include <stdio.h> #include <stdlib.h> #include <curses.h> typedef char VertexType; //頂點型別應由使用者定義 typedef int EdgeType; //邊上的權值型別應由使用者定義 #define MAXVEX 100 //最大頂點數,應由使用者定義 #define INFINITY 65535 //用65535來代表無窮大 #define DEBUG typedef struct { VertexType vexs[MAXVEX]; //頂點表 EdgeType arc[MAXVEX][MAXVEX];//鄰接矩陣,可看作邊 int numVertexes, numEdges; //圖中當前的頂點數和邊數 }Graph; //定位 int locates(Graph *g, char ch) { inti = 0; for(i = 0; i < g->numVertexes; i++) { if(g->vexs[i] == ch) { break; } } if(i >= g->numVertexes) { return -1; } return i; } //建立一個無向網圖的鄰接矩陣表示 void CreateGraph(Graph *g) { inti, j, k, w; printf("輸入頂點數和邊數:\n"); scanf("%d,%d", &(g->numVertexes), &(g->numEdges)); #ifdef DEBUG printf("%d %d\n", g->numVertexes, g->numEdges); #endif for(i = 0; i < g->numVertexes; i++) { g->vexs[i] = getchar(); while(g->vexs[i] == '\n') { g->vexs[i] = getchar(); } } #ifdef DEBUG for(i = 0; i < g->numVertexes; i++) { printf("%c ", g->vexs[i]); } printf("\n"); #endif for(i = 0; i < g->numEdges; i++) { for(j = 0; j < g->numEdges; j++) { g->arc[i][j] = INFINITY; //鄰接矩陣初始化 } } for(k = 0; k < g->numEdges; k++) { char p,q; printf("輸入邊(vi,vj)上的下標i,下標j和權值:\n"); p = getchar(); while(p == '\n') { p = getchar(); } q = getchar(); while(q == '\n') { q = getchar(); } scanf("%d", &w); int m = -1; int n = -1; m = locates(g, p); n = locates(g, q); if(n == -1 || m == -1) { fprintf(stderr,"there is no this vertex.\n"); return; } //getchar(); g->arc[m][n] = w; g->arc[n][m] = g->arc[m][n]; //因為是無向圖,矩陣對稱 } } //列印圖 void printGraph(Graph g) { int i, j; for(i = 0; i < g.numVertexes; i++) { for(j = 0; j < g.numVertexes; j++) { printf("%d ", g.arc[i][j]); } printf("\n"); } } int main(intargc, char**argv) { Graph g; //鄰接矩陣建立圖 CreateGraph(&g); printGraph(g); return 0; }
從程式碼中可以得到,n個頂點和e條邊的無向網圖的建立,時間複雜度為O(n + n2 + e),其中對鄰接矩陣Grc的初始化耗費了O(n2)的時間。
1.2 鄰接表
鄰接矩陣是不錯的一種圖儲存結構,但是,對於邊數相對頂點較少的圖,這種結構存在對儲存空間的極大浪費。因此,找到一種陣列與連結串列相結合的儲存方法稱為鄰接表。
鄰接表的處理方法是這樣的:
(1)圖中頂點用一個一維陣列儲存,當然,頂點也可以用單鏈表來儲存,不過,陣列可以較容易的讀取頂點的資訊,更加方便。
(2)圖中每個頂點vi的所有鄰接點構成一個線性表,由於鄰接點的個數不定,所以,用單鏈表儲存,無向圖稱為頂點vi的邊表,有向圖則稱為頂點vi作為弧尾的出邊表。
例如,下圖就是一個無向圖的鄰接表的結構。
從圖中可以看出,頂點表的各個結點由data和firstedge兩個域表示,data是資料域,儲存頂點的資訊,firstedge是指標域,指向邊表的第一個結點,即此頂點的第一個鄰接點。邊表結點由adjvex和next兩個域組成。adjvex是鄰接點域,儲存某頂點的鄰接點在頂點表中的下標,next則儲存指向邊表中下一個結點的指標。
對於帶權值的網圖,可以在邊表結點定義中再增加一個weight的資料域,儲存權值資訊即可。如下圖所示。
對於鄰接表結構,圖的建立程式碼如下:
/* 鄰接表表示的圖結構 */
#include <stdio.h>
#include<stdlib.h>
#define DEBUG
#define MAXVEX 1000 //最大頂點數
typedef char VertexType; //頂點型別應由使用者定義
typedef int EdgeType; //邊上的權值型別應由使用者定義
typedef struct EdgeNode //邊表結點
{
int adjvex; //鄰接點域,儲存該頂點對應的下標
EdgeType weigth; //用於儲存權值,對於非網圖可以不需要
struct EdgeNode *next; //鏈域,指向下一個鄰接點
}EdgeNode;
typedef struct VertexNode //頂點表結點
{
VertexType data; //頂點域,儲存頂點資訊
EdgeNode *firstedge; //邊表頭指標
}VertexNode, AdjList[MAXVEX];
typedef struct
{
AdjList adjList;
int numVertexes, numEdges; //圖中當前頂點數和邊數
}GraphList;
int Locate(GraphList *g, char ch)
{
int i;
for(i = 0; i < MAXVEX; i++)
{
if(ch == g->adjList[i].data)
{
break;
}
}
if(i >= MAXVEX)
{
fprintf(stderr,"there is no vertex.\n");
return -1;
}
return i;
}
//建立圖的鄰接表結構
voidCreateGraph(GraphList *g)
{
inti, j, k;
EdgeNode *e;
EdgeNode *f;
printf("輸入頂點數和邊數:\n");
scanf("%d,%d", &g->numVertexes, &g->numEdges);
#ifdef DEBUG
printf("%d,%d\n", g->numVertexes, g->numEdges);
#endif
for(i = 0; i < g->numVertexes; i++)
{
printf("請輸入頂點%d:\n", i);
g->adjList[i].data = getchar(); //輸入頂點資訊
g->adjList[i].firstedge = NULL; //將邊表置為空表
while(g->adjList[i].data == '\n')
{
g->adjList[i].data = getchar();
}
}
//建立邊表
for(k = 0; k < g->numEdges; k++)
{
printf("輸入邊(vi,vj)上的頂點序號:\n");
char p, q;
p = getchar();
while(p == '\n')
{
p = getchar();
}
q = getchar();
while(q == '\n')
{
q = getchar();
}
int m, n;
m = Locate(g, p);
n = Locate(g, q);
if(m == -1 || n == -1)
{
return;
}
#ifdef DEBUG
printf("p = %c\n", p);
printf("q = %c\n", q);
printf("m = %d\n", m);
printf("n = %d\n", n);
#endif
//向記憶體申請空間,生成邊表結點
e = (EdgeNode *)malloc(sizeof(EdgeNode));
if(e == NULL)
{
fprintf(stderr,"malloc() error.\n");
return;
}
//鄰接序號為j
e->adjvex = n;
//將e指標指向當前頂點指向的結構
e->next = g->adjList[m].firstedge;
//將當前頂點的指標指向e
g->adjList[m].firstedge = e;
f = (EdgeNode *)malloc(sizeof(EdgeNode));
if(f == NULL)
{
fprintf(stderr,"malloc() error.\n");
return;
}
f->adjvex = m;
f->next = g->adjList[n].firstedge;
g->adjList[n].firstedge = f;
}
}
void printGraph(GraphList *g)
{
inti = 0;
#ifdef DEBUG
printf("printGraph() start.\n");
#endif
while(g->adjList[i].firstedge != NULL && i < MAXVEX)
{
printf("頂點:%c ", g->adjList[i].data);
EdgeNode *e = NULL;
e = g->adjList[i].firstedge;
while(e != NULL)
{
printf("%d ", e->adjvex);
e = e->next;
}
i++;
printf("\n");
}
}
int main(intargc, char**argv)
{
GraphList g;
CreateGraph(&g);
printGraph(&g);
return0;
}
對於無向圖,一條邊對應都是兩個頂點,所以,在迴圈中,一次就針對i和j分佈進行插入。本演算法的時間複雜度,對於n個頂點e條邊來說,很容易得出是O(n+e)。
1.3 十字連結串列
對於有向圖來說,鄰接表是有缺陷的。關心了出度問題,想了解入度就必須要遍歷整個圖才知道,反之,逆鄰接表解決了入度卻不瞭解出度情況。下面介紹的這種有向圖的儲存方法:十字連結串列,就是把鄰接表和逆鄰接表結合起來的。
重新定義頂點表結點結構,如下所示。
其中firstin表示入邊表頭指標,指向該頂點的入邊表中第一個結點,firstout表示出邊表頭指標,指向該頂點的出邊表中的第一個結點。
重新定義邊表結構,如下所示。
其中,tailvex是指弧尾在頂點表的下標,headvex是指弧頭在頂點表的下標,headlink是指入邊表指標域,指向弧頭相同的下一條邊,taillink是指邊表指標域,指向弧尾相同的下一條邊。如果是網,還可以增加一個weight域來儲存權值。
比如下圖,頂點依然是存入一個一維陣列,實線箭頭指標的圖示完全與鄰接表相同。就以頂點v0來說,firstout指向的是出邊表中的第一個結點v3。所以,v0邊表結點hearvex
= 3,而tailvex其實就是當前頂點v0的下標0,由於v0只有一個出邊頂點,所有headlink和taillink都是空的。
重點需要解釋虛線箭頭的含義。它其實就是此圖的逆鄰接表的表示。對於v0來說,它有兩個頂點v1和v2的入邊。因此的firstin指向頂點v1的邊表結點中headvex為0的結點,如上圖圓圈1。接著由入邊結點的headlink指向下一個入邊頂點v2,如上圖圓圈2。對於頂點v1,它有一個入邊頂點v2,所以它的firstin指向頂點v2的邊表結點中headvex為1的結點,如上圖圓圈3。
十字連結串列的好處就是因為把鄰接表和逆鄰接表整合在一起,這樣既容易找到以v為尾的弧,也容易找到以v為頭的弧,因而比較容易求得頂點的出度和入度。而且除了結構複雜一點外,其實建立圖演算法的時間複雜度是和鄰接表相同的,因此,在有向圖應用中,十字連結串列是非常好的資料結構模型。
1.4 鄰接多重表
鄰接多重表(Adjacency Multilist)主要用於儲存無向圖。因為,如果用鄰接表儲存無向圖,每條邊的兩個邊結點分別在以該邊所依附的兩個頂點為頭結點的連結串列中,這給圖的某些操作帶來不便。例如,對已訪問過的邊做標記,或者要刪除圖中某一條邊等,都需要找到表示同一條邊的兩個結點。因此,在進行這一類操作的無向圖的問題中採用鄰接多重表作儲存結構更為適宜。鄰接多重表的儲存結構和十字連結串列類似,也是由頂點表和邊表組成,每一條邊用一個結點表示,其頂點表結點結構和邊表結點結構如圖所示。
其中,頂點表由兩個域組成,vertex 域儲存和該頂點相關的資訊firstedge 域指示第一條依附於該頂點的邊;邊表結點由六個域組成,mark為標記域,可用以標記該條邊是否被搜尋過;ivex 和
jvex 為該邊依附的兩個頂點在圖中的位置;ilink 指向下一條依附於頂點ivex的邊;jlink 指向下一條依附於頂點jvex 的邊,info 為指向和邊相關的各種資訊的指標域。
二、圖的遍歷
圖的遍歷和樹的遍歷類似,希望從圖中某一頂點出發訪遍圖中其餘頂點,且使每一個頂點僅被訪問一次,這一過程就叫圖的遍歷。
對於圖的遍歷來說,如何避免因迴路陷入死迴圈,就需要科學地設計遍歷方案,通過有兩種遍歷次序方案:深度優先遍歷和廣度優先遍歷。
2.1 深度優先遍歷
深度優先遍歷,也有稱為深度優先搜尋,簡稱DFS。其實,就像是一棵樹的前序遍歷。
深度優先遍歷的思想:從圖中某個頂點出發,訪問該頂點的鄰接點(可採用右手原則),然後以該鄰接點為新的頂點,訪問該頂點的鄰接點。重複執行上述操作,知道當前節點沒有鄰接點為止。返回到上一個被訪問過但還有未被訪問的鄰接點的頂點,按照以上步驟繼續訪問該頂點的其他未被訪問的鄰接點。以此類推,之道圖中所有的頂點都被訪問為止。
用鄰接矩陣的方式,則程式碼如下所示:
#define MAXVEX 100 //最大頂點數
typedefint Boolean; //Boolean 是布林型別,其值是TRUE 或FALSE
Boolean visited[MAXVEX]; //訪問標誌陣列
#define TRUE 1
#define FALSE 0
//鄰接矩陣的深度優先遞迴演算法
voidDFS(Graph g, inti)
{
intj;
visited[i] = TRUE;
printf("%c ", g.vexs[i]); //列印頂點,也可以其他操作
for(j = 0; j < g.numVertexes; j++)
{
if(g.arc[i][j] == 1 && !visited[j])
{
DFS(g, j); //對為訪問的鄰接頂點遞迴呼叫
}
}
}
//鄰接矩陣的深度遍歷操作
voidDFSTraverse(Graph g)
{
inti;
for(i = 0; i < g.numVertexes; i++)
{
visited[i] = FALSE; //初始化所有頂點狀態都是未訪問過狀態
}
for(i = 0; i < g.numVertexes; i++)
{
if(!visited[i]) //對未訪問的頂點呼叫DFS,若是連通圖,只會執行一次
{
DFS(g,i);
}
}
}
如果使用的是鄰接表儲存結構,其DFSTraverse函式的程式碼幾乎是相同的,只是在遞迴函式中因為將陣列換成了連結串列而有不同,程式碼如下:
//鄰接表的深度遞迴演算法
voidDFS(GraphList g, inti)
{
EdgeNode *p;
visited[i] = TRUE;
printf("%c ", g->adjList[i].data); //列印頂點,也可以其他操作
p = g->adjList[i].firstedge;
while(p)
{
if(!visited[p->adjvex])
{
DFS(g, p->adjvex); //對訪問的鄰接頂點遞迴呼叫
}
p = p->next;
}
}
//鄰接表的深度遍歷操作
voidDFSTraverse(GraphList g)
{
inti;
for(i = 0; i < g.numVertexes; i++)
{
visited[i] = FALSE;
}
for(i = 0; i < g.numVertexes; i++)
{
if(!visited[i])
{
DFS(g, i);
}
}
}
對比兩個不同的儲存結構的深度優先遍歷演算法,對於n個頂點e條邊的圖來說,鄰接矩陣由於是二維陣列,要查詢某個頂點的鄰接點需要訪問矩陣中的所有元素,因為需要O(n2)的時間。而鄰接表做儲存結構時,找鄰接點所需的時間取決於頂點和邊的數量,所以是O(n+e)。顯然對於點多邊少的稀疏圖來說,鄰接表結構使得演算法在時間效率上大大提高。
2.2 廣度優先遍歷
廣度優先遍歷,又稱為廣度優先搜尋,簡稱BFS。圖的廣度優先遍歷就類似於樹的層序遍歷了。
廣度優先遍歷的思想:從圖的某個頂點V出發,首先訪問頂點V,然後按照次序訪問頂點V的未被訪問的每一個鄰接點,接著訪問這些鄰接點的鄰接點,並保證遵循先被訪問的鄰接點的鄰接點先訪問,後被訪問的鄰接點的鄰接點後訪問的原則,以此訪問鄰接點的鄰接點。
鄰接矩陣做儲存結構時,廣度優先搜尋的程式碼如下:
//鄰接矩陣的廣度遍歷演算法
voidBFSTraverse(Graph g)
{
inti, j;
Queue q;
for(i = 0; i < g.numVertexes; i++)
{
visited[i] = FALSE;
}
InitQueue(&q);
for(i = 0; i < g.numVertexes; i++)//對每個頂點做迴圈
{
if(!visited[i]) //若是未訪問過
{
visited[i] = TRUE;
printf("%c ", g.vexs[i]); //列印結點,也可以其他操作
EnQueue(&q, i); //將此結點入佇列
while(!QueueEmpty(q)) //將隊中元素出佇列,賦值給
{
int m;
DeQueue(&q, &m);
for(j = 0; j < g.numVertexes; j++)
{
//判斷其他頂點若與當前頂點存在邊且未訪問過
if(g.arc[m][j] == 1 && !visited[j])
{
visited[j] = TRUE;
printf("%c ", g.vexs[j]);
EnQueue(&q, j);
}
}
}
}
}
}
對於鄰接表的廣度優先遍歷,程式碼與鄰接矩陣差異不大, 程式碼如下:
//鄰接表的廣度遍歷演算法
voidBFSTraverse(GraphList g)
{
inti;
EdgeNode *p;
Queue q;
for(i = 0; i < g.numVertexes; i++)
{
visited[i] = FALSE;
}
InitQueue(&q);
for(i = 0; i < g.numVertexes; i++)
{
if(!visited[i])
{
visited[i] = TRUE;
printf("%c ", g.adjList[i].data); //列印頂點,也可以其他操作
EnQueue(&q, i);
while(!QueueEmpty(q))
{
intm;
DeQueue(&q, &m);
p = g.adjList[m].firstedge; 找到當前頂點邊錶鏈表頭指標
while(p)
{
if(!visited[p->adjvex])
{
visited[p->adjvex] = TRUE;
printf("%c ", g.adjList[p->adjvex].data);
EnQueue(&q, p->adjvex);
}
p = p->next;
}
}
}
}
}
對比圖的深度優先遍歷與廣度優先遍歷演算法,會發現,它們在時間複雜度上是一樣的,不同之處僅僅在於對頂點的訪問順序不同。可見兩者在全圖遍歷上是沒有優劣之分的,只是不同的情況選擇不同的演算法。
相關推薦
圖的儲存結構及遍歷演算法
一、圖的儲存結構 1.1 鄰接矩陣 圖的鄰接矩陣儲存方式是用兩個陣列來表示圖。一個一維陣列儲存圖中頂點資訊,一個二維陣列(鄰接矩陣)儲存圖中的邊或弧的資訊。 設圖G有n個頂點,則鄰接矩陣是一個n*n的方陣,定義為: 看一個例項,下圖左就
圖的資料結構及遍歷演算法
圖的鄰接矩陣結構: public class GraphArray<T> { private int[][] edges; // 鄰接矩陣 private T[] vert
資料結構作業14—圖的概念 儲存結構和遍歷
2-1若無向圖G =(V,E)中含7個頂點,要保證圖G在任何情況下都是連通的,則需要的邊數最少是: (3分) A.16 B.21 C.15 D.6 作者: DS課程組 單位: 浙江大學 2-2對於有向圖,其鄰接矩陣表示比鄰接表
資料結構作業14—圖的概念 儲存結構和遍歷(判斷題)
1-1用鄰接矩陣法儲存圖,佔用的儲存空間數只與圖中結點個數有關,而與邊數無關。 (1分) T F 作者: DS課程組 單位: 浙江大學 1-2用鄰接表法儲存圖,佔用的儲存空間數只與圖中結點個數有關,而與邊數無關。 (1分) T
圖的表示及遍歷
1. 圖的表示 1)臨接矩陣 使用二維陣列arr[N][N]表示一個圖。 a. N 為圖的頂點個數,矩陣的對角線全為0。 b. 兩個頂點連通的話,矩陣的值為1 c. 某一行的和表示該頂點的出度。某一列的和表示該頂點的入度 d. 有權值的圖,矩陣元素不再是0,1表示是否連通,而是把元素值表示為權值。
Python資料結構--樹遍歷演算法
1 ''' 2 遍歷是訪問樹的所有節點的過程,也可以列印它們的值。 因為所有節點都通過邊(連結)連線,所以始終從根(頭)節點開始。 3 也就是說,我們不能隨機訪問樹中的一個節點。 這裡介紹三種方式來遍歷一棵樹 -順序遍歷 -前序遍歷 -後序遍歷 4 ''' 5 6 7 class No
二叉樹的順序儲存實現及遍歷
關於二叉樹的實現,常見的大概有三種實現方法: 順序儲存:採用陣列來記錄二叉樹的所有節點 二叉連結串列儲存: 每個節點保留一個left,right域,指向左右孩子 三叉連結串列儲存: 每個節點保留一個left, right, parent域,
廣度優先搜尋BFS 之圖的構造及遍歷
1. 由給定的頂點和邊的資訊構造圖的鄰接矩陣儲存; 對該圖進行深度優先搜尋,輸出搜尋得到的結點序列; 3. 以鄰接表作儲存結構,用克魯斯卡爾演算法構造最小生成樹。 /* 5 6 abcde 0 1 10 0 3 20 1 2 30 1 4 40 2 3 50 2 4 6
圖的廣度優先遍歷演算法
前言 廣度優先遍歷演算法是圖的另一種基本遍歷演算法,其基本思想是盡最大程度輻射能夠覆蓋的節點,並對其進行訪問。以迷宮為例,深度優先搜尋更像是一個人在走迷宮,遇到沒有走過就標記,遇到走過就退一步重新走;而廣度優先搜尋則可以想象成一組人一起朝不同的方向走迷宮,當出
圖的廣度優先遍歷演算法運用佇列主針對鄰接表有向圖
原始碼如下:</pre><pre name="code" class="objc">#include<iostream> using namespace std; #define MAX_VERTEX_NUM 20 typedef int
【unity3d-C#學習筆記】C#中常用的資料結構及遍歷方法
常用的集合類:ArrayList,Queue,Stack,SortedList,Hashtable 陣列: Array: 1.資料儲存在連續的記憶體上。 2.陣列的語速都是同類型的。 3.陣列
檢測是否為連通圖(深度優先遍歷演算法)
(一)九度上一個練習題 題目描述: 給定一個無向圖和其中的所有邊,判斷這個圖是否所有頂點都是連通的。 輸入: 每組資料的第一行是兩個整數 n 和 m(0<=n<=1000)。n 表示圖的頂點數目,m 表示圖中邊的數目。如果 n 為 0 表示輸
二叉樹的鏈式儲存實現及遍歷
關於二叉樹鏈式實現,常見的為如下兩種: 二叉連結串列儲存: 每個節點保留一個left,right域,指向左右孩子 三叉連結串列儲存: 每個節點保留一個left, right, parent域,指向左右孩子和父親 故對於每個二叉樹的節點
資料結構 圖的鄰接表儲存結構及DFS/BFS遍歷
//鄰接表 #include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #define INF 999 using namespace std; typedef
C語言實現圖的鄰接矩陣儲存結構及深度優先遍歷和廣度優先遍歷
DFS的核心思想在於對訪問的鄰接節點進行遞迴呼叫;BFS的核心思想在於建立了一個鄰接節點的佇列。 在Dev C++中除錯執行通過。 用下圖進行了測試。 #include <stdio.h> #define MaxVertexNum 50 #defin
實驗四:圖的基本儲存結構及圖的遍歷運算
用臨接矩陣儲存圖,輸出深度優先遍歷的頂點序列: #include <cstdlib> #include <iostream> using namespace std; typedef struct { int n,e; }Graph; Graph G; int Adj[
資料結構作業——圖的儲存及遍歷(鄰接矩陣、鄰接表+DFS遞迴、非遞迴+BFS)
鄰接矩陣存圖 /* * @Author: WZY * @School: HPU * @Date: 2018-11-02 18:35:27 * @Last Modified by: WZY * @Last Modified time: 2018-11-0
資料結構基礎之圖(中):圖的遍歷演算法
轉自:http://www.cnblogs.com/edisonchou/p/4676876.html 圖(中):圖的遍歷演算法 上一篇我們瞭解了圖的基本概念、術語以及儲存結構,還對鄰接表結構進行了模擬實現。本篇我們來了解一下圖的遍歷,和樹的遍歷類似,從圖的某一頂點出發訪問
鄰接連結串列存圖及遍歷——————資料結構作業
實現 鄰接連結串列存圖 DFS遞迴遍歷 DFS非遞迴遍歷 BFS遞迴遍歷 #include<bits/stdc++.h> using namespace std; const int MAXN = 1e4; vector<int
鄰接矩陣存圖及遍歷——————資料結構作業
實現 鄰接矩陣存圖 DFS遞迴遍歷 DFS非遞迴遍歷 BFS遞迴遍歷 #include<cstdio> #include<cstring> #include<queue> #include<stack>