码农知识堂 - 1000bd
  •   Python
  •   PHP
  •   JS/TS
  •   JAVA
  •   C/C++
  •   C#
  •   GO
  •   Kotlin
  •   Swift
  • [数据结构] 图---图的邻接矩阵存储方式模拟实现,包括BFS广度优先遍历和DFS深度优先遍历(上)


    图的邻接矩阵存储

    • 1)邻接矩阵表示法
      • 相关概念
      • 实现基础框架
        • Graph_matrix
        • 构造函数
      • 实现基础操作
        • 获取某一顶点的下标
        • 添加边
        • 打印邻接矩阵
    • 2)BFS广度优先遍历
    • 3)DFS深度优先遍历
    • 4)最小生成树之克鲁斯卡尔算法
    • 5)最小生成树之普里姆算法
    • 6)单源最短路径之迪杰斯特拉算法
    • 7)单源最短路径之贝尔曼福特算法
    • 8)多源最短路径之弗洛伊德算法

    1)邻接矩阵表示法

    相关概念

    • 如下图所示:适合存储稠密图,==O(1)==时间复杂度内判断两个顶点间的连接关系,并得到权值
      邻接矩阵

    实现基础框架

    Graph_matrix

    template <class V, class W, W MAX_W=INT_MAX, bool Direction = false>
    //模板参数依次为:顶点、权重、是否有向
    struct Graph_matrix{
    public:
    	Graph_matrix() = default;
    private:
    	vector<V> _vertex;
    	unordered_map<V, int> _indexMap;  //顶点与下标的映射关系
    	vector<vector<W>> _matrix;  //用顶点下标表示边的关系
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    构造函数

    • 初始化_vertex顶点表,并记录顶点与下标的映射关系;初始化_matrix边矩阵
    Graph_matrix(const V* _array, size_t n){
    		//初始化_vertex,记录各顶点与下标的映射关系
    		_vertex.reserve(n);
    		for (size_t i = 0; i < n; i++){
    			_vertex.push_back(_array[i]);
    			_indexMap[_array[i]] = i;
    		}
    
    		//初始化邻接矩阵
    		_matrix.resize(n);
    		for (size_t i = 0; i < n; i++){
    			_matrix[i].resize(n);
    			for (size_t j = 0; j < n; j++){
    				_matrix[i][j] = MAX_W;
    			}
    		}
    	}
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    实现基础操作

    获取某一顶点的下标

    size_t getVertexIndex(const V& v){
    		auto ret = _indexMap.find(v);
    		if (ret != _indexMap.end()){
    			return ret->second;
    		}
    		else{
    			return -1;
    		}
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    添加边

    void addEdge(const V& src, const V& dst, const W& w){
    		int srcindex = getVertexIndex(src);
    		int dstindex = getVertexIndex(dst);
    		_matrix[srci][dsti] = w;
    		//无向图要处理对称的地方
    		if (Direction == false){
    			_matrix[dsti][srci] = w;
    		}
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    打印邻接矩阵

    void print(){
    		for (auto e : _indexMap){
    			cout << e.first << "->" << e.second << endl;
    		}
    
    		cout << "  ";
    		for (size_t i = 0; i < _vertex.size(); i++){
    			cout << i << " ";
    		}
    		cout << endl;
    
    		for (size_t i = 0; i < _matrix.size(); i++){
    			cout << i << " ";
    			for (size_t j = 0; j < _matrix[0].size(); j++){
    				if (_matrix[i][j] == MAX_W){
    					cout << "* ";
    				}
    				else{
    					cout << _matrix[i][j] << " ";
    				}
    			}
    			cout << endl;
    		}
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    2)BFS广度优先遍历

    • 利用层次遍历 + 标记已访问过的顶点(已入队列)
    	//从某一顶点开始广度优先搜索
    	void BFS(const V& src){
    		size_t n = _vertex.size();
    		vector<bool> visited(n, false);  //标记访问过的顶点
    		
    		queue<V> qu;
    		int srci = getVertexIndex(src);
    		qu.push(srci);
    		visited[srci] = true;
    
    		while (!qu.empty()){
    			int cur = qu.front();
    			qu.pop();
    			cout << cur << "-> ";
    			for (size_t i = 0; i < n; i++){  //让src的邻接顶点依次入队
    				if (_matrix[cur][i] != MAX_W && visited[i] == false){
    					qu.push(i);
    					visited[i] = true;
    				}
    			}
    		}
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    3)DFS深度优先遍历

    • 先访问src顶点并标记,然后找与src相邻且没有被访问过的顶点,递归
    	//从某一顶点开始深度优先搜索
    	void _DFS(int srci, vector<bool>& visited){
    		size_t n = _vertex.size();
    
    		cout << srci << "-> ";
    		visited[srci] = true;
    
    		//找与src相邻且没有被访问过的顶点,递归
    		for (size_t i = 0; i < n; i++){
    			if (_matrix[srci][i] != MAX_W && visited[i] == false){
    				_DFS(i, visited);
    			}
    		}
    	}
    	
    	void DFS(const V& src){
    		int srci = getVertexIndex(src);
    		vector<bool> visited(_vertex.size(), false);
    		_DFS(srci, visited);
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    4)最小生成树之克鲁斯卡尔算法

    查看克鲁斯卡尔算法的代码实现

    5)最小生成树之普里姆算法

    查看普里姆算法的代码实现

    6)单源最短路径之迪杰斯特拉算法

    查看迪杰斯特拉算法的代码实现

    7)单源最短路径之贝尔曼福特算法

    查看贝尔曼福特算法的代码实现

    8)多源最短路径之弗洛伊德算法

    查看弗洛伊德算法的代码实现

  • 相关阅读:
    Stable Diffusion部署教程,开启你的AI绘图之路
    HTML CSS JS 网页设计作业「我的家乡吉林」
    看完这篇 教你玩转渗透测试靶机vulnhub——FunBox5(NEXT LEVEL)
    使用C++实现MySQL数据库编程
    flutter dio 请求封装(空安全)
    vue列表跳转详情,记录列表滚动不变
    DOM,SAX,JDOM,DOM4J四种方法对比总结
    【opencv】边界模式 borderMode
    598. 区间加法 II
    Windows电脑如何手动设置IP地址和DNS?
  • 原文地址:https://blog.csdn.net/Darling_sheeps/article/details/127754662
  • 最新文章
  • 攻防演习之三天拿下官网站群
    数据安全治理学习——前期安全规划和安全管理体系建设
    企业安全 | 企业内一次钓鱼演练准备过程
    内网渗透测试 | Kerberos协议及其部分攻击手法
    0day的产生 | 不懂代码的"代码审计"
    安装scrcpy-client模块av模块异常,环境问题解决方案
    leetcode hot100【LeetCode 279. 完全平方数】java实现
    OpenWrt下安装Mosquitto
    AnatoMask论文汇总
    【AI日记】24.11.01 LangChain、openai api和github copilot
  • 热门文章
  • 十款代码表白小特效 一个比一个浪漫 赶紧收藏起来吧!!!
    奉劝各位学弟学妹们,该打造你的技术影响力了!
    五年了,我在 CSDN 的两个一百万。
    Java俄罗斯方块,老程序员花了一个周末,连接中学年代!
    面试官都震惊,你这网络基础可以啊!
    你真的会用百度吗?我不信 — 那些不为人知的搜索引擎语法
    心情不好的时候,用 Python 画棵樱花树送给自己吧
    通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!
    13 万字 C 语言从入门到精通保姆级教程2021 年版
    10行代码集2000张美女图,Python爬虫120例,再上征途
Copyright © 2022 侵权请联系2656653265@qq.com    京ICP备2022015340号-1
正则表达式工具 cron表达式工具 密码生成工具

京公网安备 11010502049817号