重学数据结构系列之——图的遍历(广度优先搜索和深度优先搜索)学习来源:计蒜客

学习来源:计蒜客

1.图的基础东西

http://blog.csdn.net/u012763794/article/details/51103766


2.图的遍历是什么


什么是图的遍历呢?从图的某个顶点出发,沿图中的路径依次访问图中所有顶点,并且使得图中所有顶点都恰好被访问一次,这一过程即为图的遍历。需要注意的是,接下来讨论图的遍历时,都是特指在一个连通图上进行遍历。(你不连通我怎么遍历)

图有两种最常见的遍历算法:广度优先搜索(Breadth-First-Search,BFS)和深度优先搜索(Depth-First-Search,DFS)

简单来说广度优先是一层一层地向外扩展,深度优先是一个劲地往下走


3.广度优先搜索

注:下面的是无向图
#include <iostream>
#include <vector>
#include <cstring>
#include <queue>

using namespace std;

class Graph{
private:
	int n;	//顶点个数
	bool *visited;	//数组,用于标记对应编号的点是否已经被访问过了,
	vector<int> *edges;	//邻接表
public:
	Graph(int input_n){
		n = input_n;
		edges = new vector<int>[n];
		visited = new bool[n];
		memset(visited, 0, n);
	}
	~Graph(){
		delete[] edges;
		delete[] visited;
	}
	//插入,这里我们是当他是无向图,所以两边都一样插入到各自的邻接表中
	void insert(int x, int y){
		edges[x].push_back(y);
		edges[y].push_back(x);
	}

	//start_vertex:遍历的起点
	void bfs(int start_vertex){
		//声明一个int型的队列
		queue<int> bfs_queue;
		//将起点加入队列,并设置为已访问
		bfs_queue.push(start_vertex);
		visited[start_vertex] = true;
		//队列为空停止循环
		while (!bfs_queue.empty()) {
			//获取队首元素的编号,并输出
			int vertex = bfs_queue.front();
			cout<<vertex<<endl;
			//将其从队列删除
			bfs_queue.pop();
			//寻找vertex相邻的所以顶点,没被访问的就设置为已访问,并加加入队列,
			for (vector<int>::iterator it = edges[vertex].begin(); it != edges[vertex].end(); it++ ) {
				if (!visited[*it]) {
					visited[*it] = true;
					bfs_queue.push(*it);
				}
			}
		}
	}
};

int main(){
	int n, m, k;
	cout<<"请分别输入顶点数和边数"<<endl;
    cin >> n >> m;
    Graph g(n);
	cout<<"请分别输入无向边"<<endl;
    for (int i = 0; i < m; ++i) {
        int x, y;
        cin >> x >> y;
        g.insert(x, y);
    }
	cout<<"请输入遍历的起点"<<endl;
    cin >> k;
    g.bfs(k);
}

运行结果:

重学数据结构系列之——图的遍历(广度优先搜索和深度优先搜索)学习来源:计蒜客

4.深度优先搜索

遍历一般是无向图
#include <iostream>
#include <vector>
#include <cstring>

using namespace std;

class Graph{
private:
	int n;	//顶点数量
	vector<int> *edges;	//邻接表
	bool *visited;	//记录结点是否已经访问过了
public:
	Graph(int input_n){
		n = input_n;
		edges = new vector<int>[n];
		//初始化visited指针
		visited = new bool[n];
		memset(visited, 0, n);
	}
	~Graph(){
		delete[] edges;
		delete[] visited;
	}
	void insert(int x, int y){
		edges[x].push_back(y);
		edges[y].push_back(x);
	}
	//vertex:起点的编号
	void dfs(int vertex){
		cout<<vertex<<endl;
		visited[vertex] = true;	//标记为已访问
		//c++11可以写成下面的这一句
		//for (int adj_vertex:edges[vertex]) {	
		for (vector<int>::iterator it = edges[vertex].begin(); it != edges[vertex].end(); it++ ) {
		//遍历跟起点相邻的顶点,没被访问过就递归调用深度优先搜索
			if (!visited[*it]) {
				dfs(*it);
			}
		}
	}
};

int main(){
	int n, m, k;
	cout<<"请分别输入顶点数和边数"<<endl;
    cin >> n >> m;
    Graph g(n);
	cout<<"请分别输入无向边"<<endl;
    for (int i = 0; i < m; ++i) {
        int x, y;
        cin >> x >> y;
        g.insert(x, y);
    }
	cout<<"请输入遍历的起点"<<endl;
    cin >> k;
    g.dfs(k);
	return 0;
}

运行结果:

重学数据结构系列之——图的遍历(广度优先搜索和深度优先搜索)学习来源:计蒜客