图的遍历(递归+非递归)

图遍历一共有四种,邻接矩阵的BFS与DFS,邻接表的BFS与DFS

还有BFS(BFS没有递归!)与DFS递归与非递归;

目录

DFS

手工

邻接矩阵

递归

非递归

邻接表

递归

非递归 

BFS

手工 

更新

邻接表遍历算法

邻接矩阵算法


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

手工 

 

BFS 在访问了起始顶点 v 之后 , v 出发 , 依次访问 v 的各个未被访问过的邻接顶点 w 1 , w 2 , …, w t , 然后再顺序访问 w 1 , w 2 , …, w t 的所有还未被访问过的邻接顶点。再从这些访问过的顶点出发,再访问它们的所有还未被访问过的邻接顶点, 如此做下去,直到图中所有顶点都被访问到为止。
广度优先搜索是一种分层的搜索过程 , 每向前走一步可能访问一批顶点 , 不像深度优先搜索那样有往回退的情况。因此 , 广度优先搜索不是一个递归的过程。

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);
			}
		}
	}
}

  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值