//圖的鄰接表示
static struct ArcNode {
int adjvex; //該邊所指向的節點的位置
struct ArcNode* nextarc; //指向下一條邊的指針
int info; //該邊的信息
};
static struct VNode {
char data; //頂點信息
ArcNode* firstArc; //指向第一條邊的指針
};
static struct AGraph {
vector<VNode> adjList; //鄰接表
int n, e; //頂點數和邊數
};
//圖的深度遍歷DFS
vector<bool> visit;
void DFS(AGraph * G, int v)
{
ArcNode* p = NULL;
visit[v] = true;
//Visit(s); //頂點的訪問函數
p = G->adjList[v].firstArc;
while (p != NULL)
{
if (!visit[p->adjvex])
{
DFS(G, p->adjvex); //(1)
}
p = p->nextarc; // 指向下一條邊
}
}
/*
對比二叉樹的前序遍歷對比
void Preorder(btNode* p)
{
if(NULL != p)
{
visit(p);
preorder(p->lchild); // (2)
preorder(p->rchild); //(3)
}
}
說明一下:圖的DFS類似於二叉樹的先序遍歷。對比二者,不難發現:二叉樹中的(2)和(3)兩句爲遞歸訪問當前節點的兩個分支,
對應與圖的DFS代碼段中就是while循環內的語句(1),實現了遞歸地訪問當前頂點的多個分支,兩者十分相似。區別在於:二叉樹
只需要遞歸地訪問當前節點的兩個分支,圖的深度優先搜索遍歷則是要遞歸地訪問多個分支
*/
//圖的廣度優先遍歷
void BFS(AGraph* G, int v, vector<bool>& visit)
{
fill(visit.begin(), visit.end(), false); //清零visit數組
ArcNode* p = NULL;
queue<int> q;
//訪問頂點V,注意一定是在節點入隊之前設置訪問標記,這樣才能避免節點重複入隊列,類似於樹的先序遍歷
//如果是在節點出隊列的時候設置訪問標記,這就很大可能導致節點重複進入隊列,降低算法的效率
visit[v] = true;
q.push(v);
while (!q.empty())
{
auto front = q.front(); //這裏是節點出隊列的地方
q.pop();
p = G->adjList[front].firstArc;
while (p != NULL)
{
if (visit[p->adjvex] == false)
{
//此處加上訪問頂點p->adjvex的函數
visit[p->adjvex] = true; //設置新節點的訪問標記
q.push(p->adjvex); //該頂點入隊
}
p = p->nextarc;
}
}
}