图遍历一共有四种,邻接矩阵的BFS与DFS,邻接表的BFS与DFS
还有BFS(BFS没有递归!)与DFS递归与非递归;
目录
DFS
手工
DFS 在访问图中某一起始顶点 v 后, 由 v 出发, 访问它的任一邻接顶点 w1; 再从 w1 出发, 访问与 w1邻 接但还没有访问过的顶点 w2; 然后再从 w2 出发, 进行类似的访问, … 如此进行下去, 直至到达所有的邻接顶点都被访问过的顶点 u 为止。接着, 退回一步, 退到前一次刚访问过的顶点, 看是否还有其它没有被访问的邻接顶点。如果有, 则访问此顶点, 之后再从此顶点出发, 进行与前述类似的访问; 如果没有, 就再退回一步进行搜索。重复上述过程, 直到连通图中所有顶点都被访问过为止。
邻接矩阵
递归
template<class T, class E>
void DFS (Graph<T, E>& G, const T& v) {
//从顶点v出发对图G进行深度优先遍历的主过程
int i, loc, n = G.NumberOfVertices(); //顶点个数
bool *visited = new bool[n]; //创建辅助数组
for (i = 0; i < n; i++)
visited [i] = false; //辅助数组visited初始化
loc = G.getVertexPos(v); //顶点具体值
DFS (G, loc, visited); //从顶点0开始深度优先搜索
delete [] visited; //释放visited
};
template<class T, class E>
void DFS (Graph<T, E>& G, int v, bool visited[]) {
cout << G.getValue(v) << ' '; //访问结点V的具体值
visited[v] = true; //作已经访问标记
int w = G.getFirstNeighbor (v); //第一个邻接顶点
while (w != -1) { //若邻接顶点w存在
if ( !visited[w] )
DFS(G, w, visited); //若w未访问过, 递归访问顶点w
w = G.getNextNeighbor (v, w); //得到下一个邻接顶点,进行循环
}
};
非递归
const NO_EDGE = 10000000;
void DFS(Graph G, int startNode)
{
int vertexNum = G.weights.size();
vector<int> visited(vertexNum, 0);//设置为全0
stack<int> s;
s.push(startNode);
visited[startNode] = 1;
while (!s.empty())
{
int currentNode = s.top();
s.pop();
cout << G.getValue(v) << ' '; //访问结点V的具体值
for (int i = 0; i < vertexNum; i++) //找到未访问的结点
{
if (visited[i] == 0 && G.weights[currentNode][i] < NO_EDGE)
{
s.push(i); //使下一轮该结点所有联通但未访问的结点进行遍历入栈
visited[i] = 1; //刚访问完的做标记
}
}
}
}
邻接表
递归
/* 在邻接表代码中,data表示每一个结点的数据
dest表示邻接表每一个结点的下标(一般当做孩子),link表示dest链的单链*/
void DFS(int v)
{
cout<<NodeTable[v].data;//访问v结点
p=NodeTable[v].adj; //adj代表数据结点的指针
while(p!=NULL){
DFS(p->dest);
p=p->link;
}
}
非递归
请联系这一个章节的getFirstNeighbor()与getNextNeighbor()
(5条消息) 图的建立(邻接矩阵与邻接表)_inbSorryMaker的博客-CSDN博客https://blog.csdn.net/weixin_51578598/article/details/121128398(有些时候其实不要造轮子。。。)
void dfs(Graph &A, int k)
{
stack s; //初始化一个栈
int i;
for(i = 0; i < A.vexnum; i++)
{
vis[i] = 0;//初始化vis[];
}
s.push(k);
while(!s.Empty())
{
k = s.top();
visit(k); //访问k结点操作
vis[k] = 1;
for(i=A.getFirstNeighbour(k);i>=0;i=A.getNextNeighbour(k, i))
{
if(!vis[i])
{
s.push(i); //放进栈里但是不访问
vis[i] = true;
}
}
}
}
BFS
手工
template <class T, class E>
void BFS (Graph<T, E>& G, const T& v) {
int i, w;
int n = G.NumberOfVertices(); //图中顶点个数
bool *visited = new bool[n];
for (i = 0; i < n; i++) //全置为0(设置为未访问)
visited[i] = false;
int loc = G.getVertexPos (v); //取顶点号
cout << G.getValue (loc) << ' '; //访问顶点v
visited[loc] = true; //做已访问标记
Queue<int> Q;
Q.EnQueue (loc); //顶点进队列, 实现分层访问
while (!Q.IsEmpty() ) { //循环, 访问所有结点
Q.DeQueue (loc);
w = G.getFirstNeighbor(loc); //第一个邻接顶点
while (w != -1) { //若邻接顶点w存在
if (!visited[w]) { //若未访问过
cout << G.getValue (w) << ' '; //访问
visited[w] = true;
Q.EnQueue (w); //顶点w进队列
}
w = G.getNextNeighbor (loc, w); //找顶点loc的下一个邻接顶点
}
} //外层循环,判队列空否
delete [] visited;
};
更新
发现自己那时候太。。。
算了
我更新了最新版本的简洁算法,非递归还没实现xxx
邻接表遍历算法
#include <iostream>
#include<vector>
#include<cstring>
#include<cstdio>
#include<queue>
using namespace std;
struct Edge{ //邻接表边的定义
int to;
int w;
};
vector<Edge> a[100]; //邻接表定义
int visit[100]; //记录访问数组
void dfs(int x) { //邻接表深度优先搜索子函数,从x节点开始搜索
visit[x] = 1;
cout <<x<< endl;
for (int i = 0; i < a[x].size(); i++) {
if (!visit[a[x][i].to]) {
dfs(a[x][i].to);
}
}
}
void bfs(int x) { //邻接表广度优先搜索子函数,从x顶点开始
queue<int>Q;
visit[x]=1;
Q.push(x);
cout << x << endl;
while (!Q.empty()) {
int w = Q.front();
Q.pop();
for (int i = 0; i < a[w].size(); i++) { //by lt
if (!visit[a[w][i].to]) {
visit[a[w][i].to] = 1;
Q.push(a[w][i].to);
cout << a[w][i].to << endl;
}
}
}
}
void BFStraverse(int n){ //邻接表广度优先搜索主函数接口
for(int i=1;i<=n;i++){
if(!visit[i]){
bfs(i);
}
}
}
void DFStraverse(int n){ //邻接表深度优先搜索主函数接口
for(int i=1;i<=n;i++){
if(!visit[i]){
dfs(i);
}
}
}
-----------------------------------------------------------------------------------------------------------------------------
邻接矩阵算法
#include<iostream>
#include<queue>
#include<algorithm>
using namespace std;
int n,m;
const int maxSize = 1010;
int v[maxSize][maxSize]; //邻接矩阵的定义,0为两顶点无边,1为两个顶点有边
bool visited[maxSize]; //访问标记数组
void DFS(int v[][maxSize],int node){ //从node节点开始深搜
cout<<node<<" ";
visited[node] = true;
for(int i = 1;i <= n;i++){
if(!visited[i] && city[node][i] == 1)
{
DFS(v,i);
}
}
}
void BFS(int v[][maxSize],int node){ //从node节点广搜
queue<int> que;
visited[node] = true;
que.push(node);
while(!que.empty()){
int j = que.front();
cout<<que.front()<<" ";
que.pop();
for(int i = 1;i <= n;i++){
if(visited[i] == false && v[j][i] == 1)
{
visited[i] = true;
que.push(i);
}
}
}
}