數據結構與算法--圖的遍歷方式(深度遍歷和廣度遍歷)
1. 圖的深度優先遍歷
深度優先搜索算法:數據結構是棧。通過將頂點存入棧中,沿着路徑探索頂點,存在新的相鄰頂點就去訪問
鄰接矩陣深度遍歷思路:
1.將圖的頂點和邊的信息輸入到圖結構中
2.創建一個數組,用來標識頂點是否已經被遍歷過
3.初始化數組,將數組中元素置位 False
4.選擇頂點開始遍歷(注意非連通圖的情況)
5.進入遞歸,打印 i 對應的頂點信息,並將該頂點標識爲已遍歷
6.循環遍歷邊表,判斷當前邊表中兩個頂點是否有邊(arc[i][j] 是否等 1),並且當前頂點沒有遍歷過,則繼續遞歸遍歷
鄰接矩陣深度遍歷代碼實現:
// 深度優先
int visited[MAXVEX]; // 訪問標誌的數組
void DFS(MGraph G,int i){
// ✅ 修改標誌
visited[i] = TRUE;
printf("%c",G.vers[i]);
// ✅ 遞歸遍歷
for (int j = 0; j <= G.numNodes; j++) {
if (G.arc[i][j] == 1 && !visited[j]) {
DFS(G, j);
}
}
}
void DFSTravese(MGraph G){
// ✅ 初始化標誌數組
for (int i = 0; i < G.numNodes; i++) {
visited[i] = FALSE;
}
// ✅ 某一個頂點(防止非連通圖)
for (int i = 0; i <= G.numNodes; i++) {
// 判斷是否已經訪問
if (!visited[i]) {
DFS(G, i);
}
}
}
鄰接表深度遍歷代碼:
// 深度優先
int visited[MAXVEX]; // 訪問標誌的數組
void DFS(MGraph G,int i){
// 修改標誌
visited[i] = TRUE;
EdgeNode *p;
// 打印頂點 A
printf("%c",G.adjlist[i].data);
p = G.adjlist[i].firstedge;
while (p) {
if (!visited[p->adj_vex_index]) {
DFS(G, p->adj_vex_index);
}
p = p->next;
}
}
void DFSTravese(MGraph G){
// 初始化標誌數組
for (int i = 0; i < G.numNodes; i++) {
visited[i] = FALSE;
}
// 某一個頂點(防止非連通圖)
for (int i = 0; i <= G.numNodes; i++) {
// 判斷是否已經訪問
if (!visited[i]) {
DFS(G, i);
}
}
}
2. 圖的廣度優先遍歷
廣度優先搜索算法:數據結構是隊列。通過將頂點存入隊列中,最先入隊列的頂點先被探索。
思路:
先把 圖 旋轉,看成樹
1.把根節點放到隊列的末尾
2.每次從隊列的頭部取出一個元素,檢測這個元素是否有下一級,有則全部放到隊尾
3.找到所有要找的元素是結束程序
4.如果遍歷整個樹還沒有找到,結束程序。
廣度優先遍歷,需要用到隊列,我們先定義隊列的方法
// 定義隊列
typedef struct {
int data[MAXVEX];
int front;
int rear;
}Queue;
// 初始化
Status InitQueue(Queue *Q) {
Q->front = 0;
Q->rear = 0;
return OK;
}
// 判斷空
Status QueueEmpty(Queue Q) {
if (Q.front == Q.rear) {
return TRUE;
}
return FALSE;
}
//入隊
Status EnQueue(Queue *Q, int e) {
if ((Q->rear+1)%MAXVEX == Q->front) {
return ERROR;
}
Q->data[Q->rear] = e;
Q->rear = (Q->rear + 1)%MAXVEX;
return OK;
}
// 出隊
Status DeQueue(Queue *Q, int *e) {
if (Q->front == Q->rear) /* 隊列空的判斷 */
return ERROR;
*e = Q->data[Q->front];
Q->front = (Q->front+1)%MAXVEX;
return OK;
}
鄰接矩陣廣度優先遍歷
int visited[MAXVEX]; /* 訪問標誌的數組 */
void BFSTraverse(MGraph G){
Queue Q;
InitQueue(&Q);
// 將訪問標誌數組全部置爲"未訪問狀態FALSE"
for (int i = 0 ; i < G.numVertexes; i++) {
visited[i] = FALSE;
}
// 將訪問標誌數組全部置爲"未訪問狀態FALSE"
for (int i = 0; i < G.numNodes; i++) {
if (!visited[i]) {
visited[i] = TRUE;
printf("%c ",G.vers[i]);
// 入隊
EnQueue(&Q, i);
while (!QueueEmpty(Q)) {
// 出隊
DeQueue(&Q, &i);
for (int j = 0; j < G.numNodes; j++) {
if (G.arc[i][j] == 1 && !visited[j]) {
visited[j] = TRUE;
printf("%c ",G.vers[j]);
EnQueue(&Q, j);
}
}
}
}
}
}
鄰接表廣度優先遍歷
int visited[MAXSIZE]; /* 訪問標誌的數組 */
void BFSTraverse(GraphAdjList GL){
//1.創建結點
EdgeNode *p;
Queue Q;
InitQueue(&Q);
//2.將訪問標誌數組全部置爲"未訪問狀態FALSE"
for(int i = 0; i < GL->numVertexes; i++)
visited[i] = FALSE;
//3.對遍歷鄰接表中的每一個頂點(對於連通圖只會執行1次,這個循環是針對非連通圖)
for(int i = 0 ;i < GL->numVertexes;i++){
//4.判斷當前結點是否被訪問過.
if(!visited[i]){
visited[i] = TRUE;
//打印頂點
printf("%c ",GL->adjList[i].data);
EnQueue(&Q, i);
while (!QueueEmpty(Q)) {
DeQueue(&Q, &i);
p = GL->adjList[i].firstedge;
while (p) {
//判斷
if(!visited[p->adjvex]){
visited[p->adjvex] = TRUE;
printf("%c ",GL->adjList[p->adjvex].data);
EnQueue(&Q, p->adjvex);
}
p = p->next;
}
}
}
}
}