定義
深度優先遍歷
(1)從圖中某個初始頂點v出發,首先訪問初始頂點v。
(2)選擇一個與頂點v相鄰且沒被訪問過的頂點w,再從w出發進行深度優先搜索,直到圖中與當前頂點v鄰接的所有頂點都被訪問過為止。
(3) 利用遞歸實現,簡單但是不好理解,時間復雜度 O(n+e)。
廣度優先遍歷
(1)訪問初始點v,接着訪問v的所有未被訪問過的鄰接點v1,v2,…,vt。
(2)按照v1,v2,…,vt的次序,訪問每一個頂點的所有未被訪問過的鄰接點。
(3)依次類推,直到圖中所有和初始點v有路徑相通的頂點都被訪問過為止。
(4) 利用隊列實現, 時間復雜度 O(n+e).
實現代碼
深度優先遍歷算法
//深度優先遍歷算法
void DFS(AdjGraph *G, int v)
{
ArcNode *p;
visited[v] = 1;
printf("%d ", v);
p = G->adjlist[v].firstarc;
while(p != NULL) //p == NULL is the break of circle
{
if(visited[p->adjvex] == 0)
DFS(G, p->adjvex);
p=p->nextarc;
}
}
廣度優先遍歷算法
//廣度優先遍歷算法
void BFS(AdjGraph *G, int v)
{
int w, i;
ArcNode *p;
SqQueue *qu;
InitQueue(qu);
int visited[MAXV];
for(i = 0; i < G->n; i++)
visited[i] = 0;
printf("%2d",v);
visited[v] = 1;
enQueue(qu, v);
while( !QueueEmpty(qu))
{
deQueue(qu, w);
p = G->adjlist[w].firstarc;
while(p!=NULL)
{
if(visited[p->adjvex] == 0)
{
printf("%2d", p->adjvex);
visited[p->adjvex] = 1;
enQueue(qu, p->adjvex);
}
p = p->nextarc;
}
}
printf("\n");
}
注意理解
- 注意,DFS是基於遞歸形式的, 主要是往深入的方向去遍歷。 每次碰到可以讀取輸出的頂點就直接輸出,並且將其視作是頭節點數組,接着向它的下一個進行讀取。
- BFS則比較憨厚,他是直接在一個頭節點數組走到黑,一直到讀取NULL才肯回頭。這時候,需要利用隊列來保存被它錯過的路口,給他提供后悔葯。回頭時隊列出棧,出一顆后悔葯給他吃,讓它接着往下一個方向一直走。一直等到它把后悔葯都吃完,然后就遍歷結束了。
全部代碼
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <float.h>
#define ElemType int
#define maxsize 100
#define InfoType int
#define MAXV 100
#define MaxSize 100
#define INF 214748364
#define INFINITE INF
/////////////////////////////////////////////////
//鄰接表的結構體定義
typedef struct ANode
{
int adjvex; //該邊的鄰接點的編號,即有向邊指向的頂點編號
struct ANode *nextarc; //指向下一條邊的指針
int weight; //邊的相關的信息,如權值
} ArcNode; //邊節點的類型
typedef struct Vnode
{
InfoType info; //頂點的其他信息
int count; //存放頂點入度
ArcNode *firstarc; //指向第一個邊節點
} VNode; //鄰接表的頭節點的結構體類型
typedef struct
{
VNode adjlist[MAXV]; //頭節點的數組
int n, e; //圖的頂點數和邊數
} AdjGraph; //整個鄰接表的數據結構體類型
//////////////////////////////////////////////////
//鄰接矩陣的結構體
typedef struct S
{
int no; //頂點的編號
InfoType info; //頂點的其他信息
} VertexType; //頂點的類型
typedef struct SS
{
int edges[MAXV][MAXV]; //鄰接矩陣的數組
int n, e; //圖的頂點數和邊數
VertexType vexs[MAXV]; //存放頂點信息
} MatGraph;
///////////////////////////////////////////////////
typedef struct SSS
{
ElemType data[maxsize];
int front;
int rear;
} SqQueue; //隊列的結構體
////////////////////////////////
//Kruskal算法需要的簡化圖的結構體
typedef struct head
{
int u; //邊的起始頂點
int v; //邊的終止頂點
int w; //邊的權值
} Edge;
///////////////////////////////
///零零零零啦啦啦啦啦
int visited[MAXV] = {0};
///////////////////////////////
//隊列的操作函數集合
//由於隊列的函數在另一個文件
//所以需要聲明一下
void InitQueue(SqQueue *&q);
void DestoryQueue(SqQueue *&q);
bool QueueEmpty(SqQueue *q);
bool enQueue(SqQueue *&q, ElemType e);
bool deQueue(SqQueue *&q, ElemType &e);
/////////////////////////////////////////////////////////////////
//后序遍歷需要的一些隊列的基本函數
void InitQueue(SqQueue *&q)
{
q = (SqQueue *)malloc(sizeof(SqQueue));
q->front = q->rear = 0;
}
void DestoryQueue(SqQueue *&q)
{
free(q);
}
bool QueueEmpty(SqQueue *q)
{
return (q->front == q->rear);
}
bool enQueue(SqQueue *&q, ElemType e)
{
if ((q->rear + 1) % maxsize == q->front)
return false;
q->rear = (q->rear + 1) % maxsize;
q->data[q->rear] = e;
return true;
}
bool deQueue(SqQueue *&q, ElemType &e)
{
if (q->front == q->rear)
return false;
q->front = (q->front + 1) % maxsize;
e = q->data[q->front];
return true;
}
/////////////////////////////////////////////
void CreateAdj(AdjGraph *&G, int A[MAXV][MAXV], int n, int e)
{
int i, j;
ArcNode *p;
G = (AdjGraph *)malloc(sizeof(AdjGraph));
for (i = 0; i < n; i++)
G->adjlist[i].firstarc = NULL;
for (i = 0; i < n; i++)
for (j = n - 1; j >= 0; j--)
if (A[i][j] != 0 && A[i][j] != INF)
{
p = (ArcNode *)malloc(sizeof(ArcNode));
p->adjvex = j;
p->weight = A[i][j];
p->nextarc = G->adjlist[i].firstarc;
G->adjlist[i].firstarc = p;
}
G->n = n;
G->e = e;
}
void DispAdj(AdjGraph *G) //輸出鄰接表G
{
int i;
ArcNode *p;
for (i = 0; i < G->n; i++)
{
p = G->adjlist[i].firstarc;
printf("%3d: ", i);
while (p != NULL)
{
if (p->weight != 2147483647) //2147483647
printf("%3d[%d]→", p->adjvex, p->weight);
p = p->nextarc;
}
printf("^\n");
}
}
void DestroyAdj(AdjGraph *&G) //銷毀鄰接表
{
int i;
ArcNode *pre, *p;
for (i = 0; i < G->n; i++) //掃描所有的單鏈表
{
pre = G->adjlist[i].firstarc; //p指向第i個單鏈表的首結點
if (pre != NULL)
{
p = pre->nextarc;
while (p != NULL) //釋放第i個單鏈表的所有邊結點
{
free(pre);
pre = p;
p = p->nextarc;
}
free(pre);
}
}
free(G); //釋放頭結點數組
}
//////////////////////////////////////////////////////////
//無向圖鄰接表的深度優先算法
void DFS(AdjGraph *G, int v)
{
ArcNode *p;
visited[v] = 1;
printf("%d ", v);
p = G->adjlist[v].firstarc;
while(p != NULL) //p == NULL is the break of circle
{
if(visited[p->adjvex] == 0)
DFS(G, p->adjvex);
p=p->nextarc;
}
}
//////////////////////////////////////////////////////
void BFS(AdjGraph *G, int v)
{
int w, i;
ArcNode *p;
SqQueue *qu;
InitQueue(qu);
int visited[MAXV];
for(i = 0; i < G->n; i++)
visited[i] = 0;
printf("%2d",v);
visited[v] = 1;
enQueue(qu, v);
while( !QueueEmpty(qu))
{
deQueue(qu, w);
p = G->adjlist[w].firstarc;
while(p!=NULL)
{
if(visited[p->adjvex] == 0)
{
printf("%2d", p->adjvex);
visited[p->adjvex] = 1;
enQueue(qu, p->adjvex);
}
p = p->nextarc;
}
}
printf("\n");
}
int main ()
{
int a[4][MAXV] = {{0, 1, 1, 1},
{1, 0, 1, 1},
{1, 1, 0, 0},
{1, 1, 0, 0}};
AdjGraph* g;
CreateAdj(g, a, 4, 5);
printf("這是原始鄰接表的結構: \n");
DispAdj(g);
printf("\nthis is the Deep fist search (from '0'):\n");
DFS(g, 0);
printf("\nthis is the Broad fist search (from '0): \n");
BFS(g, 0);
system("pause");
return 0;
}
原始數據
原始數據以及運行結果