图——广度优先遍历和深度优先遍历——邻接表表示法

// ConsoleApplication2.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include "stdafx.h"
#include<iostream>
#include<vector>
#include<algorithm>
#include<numeric>
#include<list>
#include<iterator>
#include<deque>
#include<stack>
#include<algorithm>
#include<forward_list>
using namespace std;



struct Edge //边的定义
{ 
	Edge(int i):node(i),nextEdge(NULL){ }
	int node;
	Edge *nextEdge;
};
struct Node //节点的定义
{
	Node(int i):value(i),firstEdge(NULL){}
	int value;
	Edge *firstEdge;
};
struct Figure
{
	vector<Node*> nodes;//存储节点
	int nodeNums, edgeNums;
};
class Solution {
public:
	//构建表
	void createFigure(Figure &figure)
	{
		//首先输入边的信息
		cout << "请输入节点的数目:" ;
		cin >> figure.nodeNums;
		cout << "请输入边的数目:";
		cin >> figure.edgeNums;
		for (int i = 0; i < figure.nodeNums; ++i) //输入节点信息
		{
			figure.nodes.push_back(new Node(i));
		}
		for (int i = 0; i < figure.nodeNums; ++i)//输入边的信息
		{
			cout << "请输入相关的边:";
			int node1, node2;
			cin >> node1 >> node2;
			auto it = figure.nodes.begin();
			while (it!=figure.nodes.end() && node1!=(*it)->value)
			{
				it++;//找到节点
			}
			if (it != figure.nodes.end())
			{
				//第一种插入方式
				/*Edge* temp = (*it)->firstEdge;
				(*it)->firstEdge = new Edge(node2);
				(*it)->firstEdge->nextEdge = temp;*/
				//第二种插入方式:
				if ((*it)->firstEdge == NULL)
				{
					(*it)->firstEdge = new Edge(node2);
				}
				else
				{
					Edge* edge = (*it)->firstEdge;
					while (edge->nextEdge != NULL)
					{
						edge = edge->nextEdge;
					}
					edge->nextEdge = new Edge(node2);
				}
				
			}
		}
	}

	void CreateAFigure(Figure &figure)
	{
		figure.nodeNums = 6;
		for (int i = 0; i < figure.nodeNums; ++i) //输入节点信息
		{
			figure.nodes.push_back(new Node(i));
		}
		figure.nodes[0]->firstEdge = new Edge(1);
		figure.nodes[0]->firstEdge->nextEdge = new Edge(2);
		figure.nodes[1]->firstEdge = new Edge(3);
		figure.nodes[1]->firstEdge->nextEdge = new Edge(4);
		figure.nodes[2]->firstEdge = new Edge(3);
		figure.nodes[4]->firstEdge = new Edge(5);
		
	}

	void printFigure(Figure figure)//打印图
	{
		cout << "打印图的结构:" << endl;
		for (int i = 0; i < figure.nodeNums; i++)
		{
			cout <<"v_"<< figure.nodes[i]->value << ": ";
			if (figure.nodes[i]->firstEdge != NULL)
			{
			//	cout << figure.nodes[i]->firstEdge->node << "  ";
				Edge* edge = figure.nodes[i]->firstEdge;
				while (edge!=NULL)
				{
					cout << "v_"<<edge->node << "  ";
					edge = edge->nextEdge;
				}
			}
			cout << endl;
		}
	}
	//深度优先遍历
	void DFSTraver(Figure figure)
	{
		setVisit(figure);
		for (int i = 0; i < figure.nodeNums; ++i)
		{
			if (visisted[i] == false)//第i个节点没有被访问
				DFS(figure.nodes[i], figure);
		}
	}
	void DFS(Node* node,Figure figure)
	{
		
		if (visisted[node->value] == false)//如果该节点没有被访问过
		{
			cout << "v_" << node->value << "  ";
			visisted[node->value] = true;
		}
		if (node->firstEdge == NULL) return;
		if(visisted[node->firstEdge->node]==false)//第一个边没有被访问,访问第一条边
		   DFS(figure.nodes[node->firstEdge->node],figure);
		if (visisted[node->firstEdge->node] == true)//第一个边已经被访问过了,访问第二条没有被访问的边
		{
			//首先找到第一条没有被访问的边
			Edge* edge = node->firstEdge->nextEdge; //第一条可访问的边
			while (edge!=NULL)
			{
				if (visisted[edge->node] == true)//对应的节点已经访问过了
					edge = edge->nextEdge;
				else
					break;//对应的节点没有被访问过
			}
			if (edge == NULL) //初始节点对应的边都访问完了
				return;
			else
				DFS(figure.nodes[edge->node], figure);//访问第一条没有访问的边
		}
	}

	//广度优先遍历
	void BFSTravers(Figure figure)
	{
		setVisit(figure);
		for (int i = 0; i < figure.nodeNums; ++i)
		{
			if (visisted[i] == false)
			{
				BFS(figure.nodes[i], figure);
			}
			   
		}
	}
	deque<Node*> parent;
	deque<Node*> child;
	//此处应该设置两个队列;一个父队列,一个子队列,父亲队列用来存储将要答应的节点,子队列用来存储将要打印的节点
	void BFS(Node* node,Figure figure)
	{
		//if (visisted[node->value] == false)//如果该节点没有被访问过
		//{
		//	cout << "v_" << node->value << "  ";  //打印跟节点
		//	visisted[node->value] = true;
		//}
		//if (node->firstEdge == NULL) return;
		//else
		//{
		//	cout << "v_" << node->firstEdge->node << "  "; //把接下来的根节点存入队列Node中
		//	visisted[node->firstEdge->node] = true;
		//	parent.push(figure.nodes[node->firstEdge->node]);
		//}
		//Edge* edge = node->firstEdge->nextEdge;
		//while (edge!=NULL)
		//{
		//	cout << "v_" << edge->node << "  ";
		//	visisted[node->firstEdge->node] = true;
		//	parent.push(figure.nodes[edge->node]);
		//	edge = edge->nextEdge;
		//}

		child.push_back(node);
		while (!child.empty())
		{
			parent = child;
			child.clear();
			while (!parent.empty())
			{
				
				if (visisted[parent.front()->value] == false)
				{
					cout << "v_" << parent.front()->value << "  ";  //打印跟节点
					visisted[parent.front()->value] = true;
				}
				
				Edge* edge = parent.front()->firstEdge;
				while (edge!=NULL)
				{
					child.push_back(figure.nodes[edge->node]);
					edge = edge->nextEdge;
				}
				parent.pop_front();
			}
		}
		
		
	}

	vector<bool> visisted;//访问过的设置为ture,没访问过设置为false
	void setVisit(Figure figure)
	{
		visisted.clear();
		for (int i = 0; i < figure.nodeNums; i++)
		{
			visisted.push_back(false);
		}
	}
};

int main()
{

	Solution so;
	Figure figure;
	so.CreateAFigure(figure);
	cout << "节点结构:" << endl;;
	so.printFigure(figure);
	cout << "深度优先遍历:";
	so.DFSTraver(figure);
	cout << endl;
	cout << "广度优先遍历:";
	so.BFSTravers(figure);
	cout << endl;
	return 0;
}
原文地址:https://www.cnblogs.com/wdan2016/p/6182125.html