左神算法基础class6—题目2宽度优先遍历和深度优先遍历

左神算法基础class6—题目2宽度优先遍历和深度优先遍历

  • 1.题目:宽度优先遍历和深度优先遍历
  • 2.宽度优先遍历
    • (1)分析
    • (2)核心代码
  • 3.深度优先遍历
    • (1)分析
    • (2)核心代码
  • 4.完整代码

1.题目:宽度优先遍历和深度优先遍历

2.宽度优先遍历

(1)分析

宽度优先遍历指从头节点开始,按照与当前节点步数越近越先输出的原则,遍历所有节点
左神算法基础class6—题目2宽度优先遍历和深度优先遍历_第1张图片
如果从1开始,最先遍历离1最近的2,3,4,接着再是7,5,6。同一批次2,3,4或者7,5,6内部输出顺序不做要求。3节点遍历后7节点依旧指向3为了避免重复遍历,使用unordered_set结构判断是否遍历过。
具体过程如下;
①利用队列实现 ;
②从源节点开始依次按照宽度进队列,然后弹出 ;
③每弹出一个点,把该节点所有没有进过队列的邻接点放入队列;
④直到队列变空;

(2)核心代码

void bfs(Node* nodes)
{
     
	if(nodes == NULL)	return ;	//空节点直接返回 
	queue<Node*> q;
	unordered_set<Node*> set; 		//用于判断是否遍历过 
	q.push(nodes);
	set.insert(nodes);
	while(!q.empty())
	{
     
		Node* help = q.front();
		cout<<help->value<<" ";
		q.pop();
		
		//把队头指向的所有未遍历节点加入队列和set 
		for(Node* t: help->nexts)	
		{
     
			if(set.find(t) == set.end())	//未在set中
			{
     
				q.push(t);
				set.insert(t);
			}
		}
	}
} 

3.深度优先遍历

(1)分析

深度优先遍历是一条路走完再走另一条。
左神算法基础class6—题目2宽度优先遍历和深度优先遍历_第2张图片
具体过程如下:
①利用栈实现 ;
②从源节点开始把节点按照深度放入栈,然后弹出 ;
③每弹出一个点,若该节点有没有进过栈的邻接点存在,把该节点和没有进过栈的一个邻接点放入栈 ;
④直到栈变空;

对于上述的图,每一步的栈和set容器如下:
栈:1
set:1
栈:空
set:1
栈:1,2
set:1,2
栈:1,2,7
set:1,2,7
栈:1,2,7,3,
set:1,2,7,3
栈:1,2,7,3,5
set:1,2,7,3,5
栈:1,2,7,3
set:1,2,7,3,5
栈:1,2,7
set:1,2,7,3,5
栈:1,2
set:1,2,7,3,5
栈:1
set:1,2,7,3,5
栈:1,4
set:1,2,7,3,5,4
栈:1,4,6
set:1,2,7,3,5,4,6
栈:1,4
set:1,2,7,3,5,4,6
栈:1,
set栈:空
set:1,2,7,3,5,4,6

(2)核心代码

void dfs(Node* node)
{
     
	if(node == NULL)	return;
	stack<Node*> s;
	unordered_set<Node*> set;
	s.push(node); 
	set.insert(node);
	cout<<node->value<<" "; 				//第一个元素直接输出 
	while(!s.empty())
	{
     
		Node* help = s.top();
		s.pop();
		for(auto tmp : help->nexts)
		{
     
			if(set.find(tmp) == set.end())	//未遍历 
			{
     
				s.push(help);				
				s.push(tmp);
				set.insert(tmp);
				cout<<tmp->value<< " ";
				break;						//一次只找一个 
			}
		} 
	}
} 

4.完整代码

#include 
#include 
#include
#include
#include 
#include
#include 
#include"Node.h"
#include"Edge.h"
#include"Graph.h"
#include"GraphGenerator.h"
using namespace std;
/* run this program using the console pauser or add your own getch, system("pause") or input loop */

void dfs(Node* node)
{
     
	if(node == NULL)	return;
	stack<Node*> s;
	unordered_set<Node*> set;
	s.push(node); 
	set.insert(node);
	cout<<node->value<<" "; 				//第一个元素直接输出 
	while(!s.empty())
	{
     
		Node* help = s.top();
		s.pop();
		for(auto tmp : help->nexts)
		{
     
			if(set.find(tmp) == set.end())	//未遍历 
			{
     
				s.push(help);				
				s.push(tmp);
				set.insert(tmp);
				cout<<tmp->value<< " ";
				break;						//一次只找一个 
			}
		} 
	}
} 

void bfs(Node* node)
{
     
	if(node == NULL)	return ;	//空节点直接返回 
	queue<Node*> q;
	unordered_set<Node*> set; 		//用于判断是否遍历过 
	q.push(node);
	set.insert(node);
	while(!q.empty())
	{
     
		Node* help = q.front();
		cout<<help->value<<" ";
		q.pop();
		
		//把队头指向的所有未遍历节点加入队列和set 
		for(Node* t: help->nexts)	
		{
     
			if(set.find(t) == set.end())	//未在set中
			{
     
				q.push(t);
				set.insert(t);
			}
		}
	}
} 

int main(int argc, char** argv) {
     
	GraphGenerator g;
	vector<vector<int> > matrix= {
     {
     12,1,2},
								  {
     13,1,3},
								  {
     14,1,4},
								  {
     9,2,7},
								  {
     10,7,3},
								  {
     8,3,5},
								  {
     10,4,6}};
	Graph graph = g.createGraph(matrix);

	//test :某节点所指向的节点 
	cout<<"1所指向:";
	Node* testnode = graph.nodes[1];
	for(auto n : testnode->nexts)
	 	cout<< n->value<<"、";
	 	
	 	
	//test :输出所有节点与边  	
	cout<<endl<<"-----------------------------------------------"<<endl ;
	cout<<"所有节点为: "<<endl ; 
	unordered_map<int,Node*>::iterator ite1 = graph.nodes.begin();
	while(ite1 != graph.nodes.end())
	{
     
	 	cout << "节点: "<<(ite1)->second->value<<"、";
		//cout << "节点: "<<(ite1)->first<<"、";
	 	ite1++;
	}
	cout<<endl<<"-----------------------------------------------"<<endl ;
	cout<<"节点与边为: "<<endl ;
	unordered_set<Edge*>::iterator ite = graph.edges.begin();
	while(ite != graph.edges.end())
	{
     
	 	cout << "边权为 "<<(*ite)->weight<<"    ";
	 	cout<<(*ite)->from->value <<"---->"<<(*ite)->to->value<<endl; 
	 	ite++;
	}
	
	
	Node *node = graph.nodes[1];
	cout<<endl<<"-----------------------------------------------"<<endl ;
	cout<<"宽度优先遍历bfs: "<<endl;
	bfs(node);
	
	
	
	
	cout<<endl<<"-----------------------------------------------"<<endl ;
	cout<<"深度优先遍历dfs: "<<endl;
	dfs(node);
	
	return 0;
}

注:Graph.h等头文件在上一篇图的存储与表达中。

左神算法基础class6—题目2宽度优先遍历和深度优先遍历_第3张图片

你可能感兴趣的:(左神算法基础课,算法,dfs,队列,数据结构,bfs)