zoukankan      html  css  js  c++  java
  • 重学数据结构系列之——图的遍历(广度优先搜索和深度优先搜索)学习来源:计蒜客

    学习来源:计蒜客

    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;
    }
    

    运行结果:






  • 相关阅读:
    阿里云oss前端javascript签名上传爬坑手册
    关于文件上传获取视频播放时长
    用js获取视频播放时长
    关于文件上传阿里云Oss
    两种方式实现图片上传在线预览
    关于input file img实时预览获取文件路径的问题
    关于input file 改样式的操作方式
    关于jquery attr()与prop() 的区别
    弹窗确认操作的业务逻辑与几种方式
    [LintCode] Flip Bits
  • 原文地址:https://www.cnblogs.com/cnsec/p/13286547.html
Copyright © 2011-2022 走看看