图(无向图)的BFS和DFS遍历

二刷数据结构,总结归纳一下树/图的遍历区别

以前一直分不清,学的稀里糊涂的…这次系统的认真看了数据结构,实现了代码,总结了几点纳一下树/图的遍历。(使用的是王道408复习教材)

建议看一下我上一篇博客,实现的Dijkstra,收益匪浅,用时1h40m(编码小白很是欣慰==)


好了,接下来总结一下:

  • 首先,图没有根结点,不像树的遍历,可以从root开始,图的遍历一般要指定开始的结点,而且图的任意顶点都可能和其余顶点相连接,所以为避免重复访问,设置bool visited[]数组记录结点是否被访问,同时,我设置了int num去统计已经访问了的结点个数,自然而然,while()的判断条件就是while(num!=n)BFS和DFS的遍历结果并不唯一

  • BFS我大概9分钟把完整的代码写完了,需要注意的是每次要判断
    !visited[i] 这个值,题主每次判断qu.empty()时老是忘记加 !,不要学我

  • DFS第一次实现结果错了,因为 题主用邻接矩阵存储图,人为地输入 左小结点右大结点这样真的很不严谨…其实啊,无向图的邻接矩阵本来就就有冗余…而我只存了一半…导致我在入栈的时候,可能找不到相邻结点了

    输入数据时为:
    5 6 1
    1 2
    1 5
    2 3
    2 4
    3 4
    4 5
    然后1出栈,2,5入栈,5为栈顶,但是此时在邻接矩阵中5是没有相邻顶点的,所以直接出栈了,然后2位栈顶,很明显不对。然后我改了一下存储图的代码

int temp1,temp2;
	cin>>N>>M>>start;
	for(int i=1;i<=M;i++){ 
	cin>>temp1>>temp2;
	ljjz[temp1][temp2]=1;
	
	}

代码区:

/*
图的BFS与DFS算法
20:06 
20:17
*/
#include<bits/stdc++.h>
#define INF 999
using namespace std;
//采用邻接矩阵存储 
int ljjz[100][100];

void DFS(int N,int M,int s){
	vector<int>res;
	bool visited[100];
	int num_of_true=0;
	for(int i=1;i<=N;i++){
		visited[i]=false;
	}
	stack<int>st;
	st.push(s);
	while(num_of_true!=N){
		int now=st.top();
		visited[now]=true;
		++num_of_true;
		res.push_back(now);
		st.pop();
		for(int i=1;i<=N;i++){
			if(ljjz[now][i]&&!visited[i]){
				st.push(i);
			}
		}
	}
	for(int i=0;i<res.size();i++)
		cout<<res[i]<<" ";
	
	
}

void BFS(int N,int M,int s){
	vector<int>res;
	bool visited[100];
	int num_of_true=0;
	for(int i=1;i<=N;i++){
		visited[i]=false;
	}
	queue<int>qu;
	qu.push(s);
	while(num_of_true!=N){
		int now=qu.front();
		visited[now]=true;
		++num_of_true;
		res.push_back(now);
		qu.pop();
		for(int i=1;i<=N;i++){
			if(ljjz[now][i]&&!visited[i]){
				qu.push(i);
			}
		}
	}
	for(int i=0;i<res.size();i++)
		cout<<res[i]<<" ";
	
} 

int main(){
	int N,M,start;
	int temp1,temp2;
	cin>>N>>M>>start;
	for(int i=1;i<=M;i++){ 
	cin>>temp1>>temp2;
	ljjz[temp1][temp2]=1;
	ljjz[temp2][temp1]=1;
	}
//	BFS(N,M,start);
	DFS(N,M,start);
	return 0;
} 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是使用邻接表表示无向图BFSDFS的C语言代码。其中,我们假设中的节点编号从0开始。代码中的注释会帮助您理解算法的实现细节。 ```c #include <stdio.h> #include <stdlib.h> #define MAX_VERTEX_NUM 100 // 最大节点数 /* 邻接表节点结构体 */ typedef struct ArcNode{ int adjvex; // 邻接点编号 struct ArcNode* nextarc; // 下一个邻接点指针 }ArcNode; /* 顶点节点结构体 */ typedef struct VertexNode{ int data; // 顶点数据 ArcNode* firstarc; // 第一个邻接点指针 }VertexNode; /* 结构体 */ typedef struct{ VertexNode vexs[MAX_VERTEX_NUM]; // 顶点数组 int vexnum; // 顶点数 int arcnum; // 边数 }Graph; /* 初始化 */ void InitGraph(Graph* G){ int i; G->vexnum = 0; G->arcnum = 0; for(i = 0; i < MAX_VERTEX_NUM; i++){ G->vexs[i].data = 0; G->vexs[i].firstarc = NULL; } } /* 插入边 */ void InsertArc(Graph* G, int v1, int v2){ ArcNode* p1 = (ArcNode*)malloc(sizeof(ArcNode)); ArcNode* p2 = (ArcNode*)malloc(sizeof(ArcNode)); p1->adjvex = v2; p2->adjvex = v1; p1->nextarc = G->vexs[v1].firstarc; p2->nextarc = G->vexs[v2].firstarc; G->vexs[v1].firstarc = p1; G->vexs[v2].firstarc = p2; G->arcnum++; } /* BFS */ void BFS(Graph* G, int start){ int visited[MAX_VERTEX_NUM] = {0}; // 初始化所有节点未被访问 int queue[MAX_VERTEX_NUM]; // 队列 int front = 0; // 队头 int rear = 0; // 队尾 int i, j; ArcNode* p; visited[start] = 1; // 标记起始节点已被访问 printf("%d ", start); // 输出起始节点 queue[rear++] = start; // 起始节点入队 while(front < rear){ // 队列不为空则循环 i = queue[front++]; // 出队 p = G->vexs[i].firstarc; // 获取第一个邻接点 while(p){ // 遍邻接点 j = p->adjvex; if(!visited[j]){ // 如果邻接点未被访问则访问并标记 visited[j] = 1; printf("%d ", j); queue[rear++] = j; // 邻接点入队 } p = p->nextarc; // 处理下一个邻接点 } } } /* DFS */ void DFS(Graph* G, int i, int visited[]){ ArcNode* p = G->vexs[i].firstarc; // 获取第一个邻接点 visited[i] = 1; // 标记节点已被访问 printf("%d ", i); // 输出节点 while(p){ // 遍邻接点 if(!visited[p->adjvex]){ // 如果邻接点未被访问则递归访问 DFS(G, p->adjvex, visited); } p = p->nextarc; // 处理下一个邻接点 } } int main(){ Graph G; int start; int i, j; printf("请输入无向图的节点数和边数:"); scanf("%d%d", &G.vexnum, &G.arcnum); printf("请依次输入每个节点的数据:"); for(i = 0; i < G.vexnum; i++){ scanf("%d", &(G.vexs[i].data)); } printf("请依次输入每条边的两个节点编号(从0开始):\n"); for(i = 0; i < G.arcnum; i++){ scanf("%d%d", &j, &start); InsertArc(&G, j, start); } printf("请输入遍开始的节点编号(从0开始):"); scanf("%d", &start); printf("BFS结果为:"); BFS(&G, start); printf("\nDFS结果为:"); int visited[MAX_VERTEX_NUM] = {0}; // 初始化所有节点未被访问 DFS(&G, start, visited); return 0; } ``` 希望这份代码能够帮到您!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值