二刷数据结构,总结归纳一下树/图的遍历区别
以前一直分不清,学的稀里糊涂的…这次系统的认真看了数据结构,实现了代码,总结了几点纳一下树/图的遍历。(使用的是王道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;
}