热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

图论(上)无权图

图论Graphtheory基础研究由点和边组成的数学模型应用:交通运输社交网络互联网工作安排脑区活动程序状态执行图的分类图的连通性简单图(SimpleGraph)图的
图论Graph theory 基础

研究由点和边组成的数学模型
graph theory

应用:
交通运输
社交网络
互联网
工作安排
脑区活动
程序状态执行

图的分类

default

2

图的连通性

default

简单图(Simple Graph)

simple graph

图的表示

邻接表适合表示稀疏图(Sparse Graph)
邻接矩阵适合表示稠密图(Dense Graph)

邻接矩阵

表示无向图
default
表示有向图
default

邻接表

表示无向图
default

表示有向图
default

图的实现

邻接矩阵

public class DenseGraph {private int n;// 节点数private int m;// 边数private boolean directed;//是否为有向图private boolean[][] g;// 图的具体数据public DenseGraph(int n, boolean directed) {this.n &#61; n;this.m &#61; 0;this.directed &#61; directed;g &#61; new boolean[n][n];}public int getNodesCount() {return n;}public int getEdgesCount(){return m;}public void addEdge(int v, int w) {if (v <0 || v >&#61; n || w <0 || w >&#61; n) {return;} if (hasEdge(v, w)) {return;}g[v][w] &#61; true;if (!directed) {g[w][v] &#61; true;}m&#43;&#43;;}public boolean hasEdge(int v, int w) {if (v <0 || v >&#61; n || w <0 || w >&#61; n) {return false;} return g[v][w];}
}

邻接表

public class SparseGraph {private int n, m;private boolean directed;private List> g;public SparseGraph(int n, boolean) {if (n <0) {return;}this.n &#61; n;this.m &#61; 0;this.directed &#61; directed;g &#61; (ArrayList[])new ArrayList[n];}public int getNodesCount() {return n;}public int getEdgesCount() {return m;}public boolean hasEdge(int v, int w) {if (v <0 || v >&#61; n || w <0 || w >&#61; n) {return false;}int n &#61; g[v].size();for (int i &#61; 0; i &#61; n || w <0 || w >&#61; n) {return;}//如果不允许平行边&#xff0c;需要加这样的判断if (hasEdge(v, w)) {return;}//如果允许平行边&#xff0c;注释掉上述判断g[v].add(w);if (v !&#61; w && !directed) {g[w].add(v);}m&#43;&#43;;}
}
遍历边

返回一个节点的所有邻边

对于稀疏图来说

返回当前行即可

public Iterable adj(int v) {if (v <0 || v >&#61; n) {return new ArrayList();}return g[v];}

对于稠密图来说

需要遍历一下&#xff0c;代码如下&#xff1a;

public Iterable adj(int v) {List res &#61; new ArrayList<>();if (v <0 || v >&#61; n) {return res;}for (int i &#61; 0; i

边的遍历对图的遍历至关重要&#xff01;

阶段重构

抽象一个图的接口

public interface Graph {public int getNodesCount();public int getEdgesCount();public void addEdge(int v, int w);public boolean hasEdge(int v, int w);public Iterable adj(int v);
}

将DenseGraph和SparseGraph修改为实现Graph接口

图的遍历

深度优先遍历

从一个节点开始&#xff0c;不断向下&#xff0c;直到无法进行为止&#xff0c;由于图可能有环&#xff0c;因此需要记录遍历过程中的点。

求一个图的联通分量

以求一个图的联通分量来展示图的深度优先遍历

//求无权图的联通分量public class Component {private Graph g;private boolean[] visited;// 记录dfs的过程中节点是否被访问private int ccount;// 记录联通分量个数private int[] id;// 每个节点所对应的联通分量标记public Component(Graph g) {this.g &#61; g;int n &#61; g.getNodesCount();visited &#61; new boolean[n];id &#61; new int[n];ccount &#61; 0;//初始化for (int i &#61; 0; i &#61; n || w <0 || w >&#61; n) {return false;}return id[v] &#61;&#61; id[w];}}

求两点的路径

public class Path {private Graph g;private boolean[] visited;private int s;private int[] from;public Path(Graph g, int s) {this.g &#61; g;this.s &#61; s;int n &#61; g.getNodesCount();visited &#61; new boolean[n];from &#61; new int[n];for (int i &#61; 0; i &#61; g.getNodesCount()) {return false;}return visited[w];}public List path(int w) {List res &#61; new ArrayList<>();if (w <0 || w >&#61; g.getNodesCount()) {return res;}Stack s &#61; new Stack<>();int p &#61; w;while (p !&#61; -1) {s.push(p);p &#61; from[p];}while (!s.isEmpty()) {res.add(s.pop());}return res;}
}

深度遍历复杂度
稀疏图O(V&#43;E)
稠密图O(V^2)
深度优先遍历对有向图依旧有效

广度优先遍历

又称为层序遍历&#xff0c;以两点间的最短路径为例

public class ShortestPath {private Graph g;private int s;private boolean[] visited;private int[] from;private int[] order;public ShortestPath(Graph g, int s) {this.g &#61; g;this.s &#61; s;int n &#61; g.getNodesCount();from &#61; new int[n];visited &#61; new boolean[n];order &#61; new int[n];for (int i &#61; 0; i queue &#61; new LinkedList<>();queue.offer(s);visited[s] &#61; true;order[s] &#61; 0;while (!queue.isEmpty()) {int v &#61; queue.poll();for (int i : g.adj()) {if (!visited[i]) {queue.offer(i);visited[i] &#61; true;from[i] &#61; v;order[i] &#61; order[v] &#43; 1;}}}}public boolean hasPath(int w) {if (w <0 || w >&#61; g.getNodesCount()) {return false;}return visited[w];}public List path(int w) {List res &#61; new ArrayList<>();if (w <0 || w >&#61; g.getNodesCount()) {return res;}Stack s &#61; new Stack<>();int p &#61; w;while (p !&#61; -1) {s.push(p);p &#61; from[p];}while (!s.isEmpty()) {res.add(s.pop());}return res;}public int length(int w) {if (w <0 || w >&#61; g.getNodesCount()) {return -1;}return order[w];}
}



推荐阅读
  • STL迭代器的种类及其功能介绍
    本文介绍了标准模板库(STL)定义的五种迭代器的种类和功能。通过图表展示了这几种迭代器之间的关系,并详细描述了各个迭代器的功能和使用方法。其中,输入迭代器用于从容器中读取元素,输出迭代器用于向容器中写入元素,正向迭代器是输入迭代器和输出迭代器的组合。本文的目的是帮助读者更好地理解STL迭代器的使用方法和特点。 ... [详细]
  • 模板引擎StringTemplate的使用方法和特点
    本文介绍了模板引擎StringTemplate的使用方法和特点,包括强制Model和View的分离、Lazy-Evaluation、Recursive enable等。同时,还介绍了StringTemplate语法中的属性和普通字符的使用方法,并提供了向模板填充属性的示例代码。 ... [详细]
  • 深入解析Linux下的I/O多路转接epoll技术
    本文深入解析了Linux下的I/O多路转接epoll技术,介绍了select和poll函数的问题,以及epoll函数的设计和优点。同时讲解了epoll函数的使用方法,包括epoll_create和epoll_ctl两个系统调用。 ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • 本文分享了一个关于在C#中使用异步代码的问题,作者在控制台中运行时代码正常工作,但在Windows窗体中却无法正常工作。作者尝试搜索局域网上的主机,但在窗体中计数器没有减少。文章提供了相关的代码和解决思路。 ... [详细]
  • CSS3选择器的使用方法详解,提高Web开发效率和精准度
    本文详细介绍了CSS3新增的选择器方法,包括属性选择器的使用。通过CSS3选择器,可以提高Web开发的效率和精准度,使得查找元素更加方便和快捷。同时,本文还对属性选择器的各种用法进行了详细解释,并给出了相应的代码示例。通过学习本文,读者可以更好地掌握CSS3选择器的使用方法,提升自己的Web开发能力。 ... [详细]
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • 本文介绍了Redis的基础数据结构string的应用场景,并以面试的形式进行问答讲解,帮助读者更好地理解和应用Redis。同时,描述了一位面试者的心理状态和面试官的行为。 ... [详细]
  • JavaSE笔试题-接口、抽象类、多态等问题解答
    本文解答了JavaSE笔试题中关于接口、抽象类、多态等问题。包括Math类的取整数方法、接口是否可继承、抽象类是否可实现接口、抽象类是否可继承具体类、抽象类中是否可以有静态main方法等问题。同时介绍了面向对象的特征,以及Java中实现多态的机制。 ... [详细]
  • 本文介绍了在Vue项目中如何结合Element UI解决连续上传多张图片及图片编辑的问题。作者强调了在编码前要明确需求和所需要的结果,并详细描述了自己的代码实现过程。 ... [详细]
  • Redis底层数据结构之压缩列表的介绍及实现原理
    本文介绍了Redis底层数据结构之压缩列表的概念、实现原理以及使用场景。压缩列表是Redis为了节约内存而开发的一种顺序数据结构,由特殊编码的连续内存块组成。文章详细解释了压缩列表的构成和各个属性的含义,以及如何通过指针来计算表尾节点的地址。压缩列表适用于列表键和哈希键中只包含少量小整数值和短字符串的情况。通过使用压缩列表,可以有效减少内存占用,提升Redis的性能。 ... [详细]
  • 李逍遥寻找仙药的迷阵之旅
    本文讲述了少年李逍遥为了救治婶婶的病情,前往仙灵岛寻找仙药的故事。他需要穿越一个由M×N个方格组成的迷阵,有些方格内有怪物,有些方格是安全的。李逍遥需要避开有怪物的方格,并经过最少的方格,找到仙药。在寻找的过程中,他还会遇到神秘人物。本文提供了一个迷阵样例及李逍遥找到仙药的路线。 ... [详细]
  • 本文介绍了使用哈夫曼树实现文件压缩和解压的方法。首先对数据结构课程设计中的代码进行了分析,包括使用时间调用、常量定义和统计文件中各个字符时相关的结构体。然后讨论了哈夫曼树的实现原理和算法。最后介绍了文件压缩和解压的具体步骤,包括字符统计、构建哈夫曼树、生成编码表、编码和解码过程。通过实例演示了文件压缩和解压的效果。本文的内容对于理解哈夫曼树的实现原理和应用具有一定的参考价值。 ... [详细]
  • 本文介绍了Codeforces Round #321 (Div. 2)比赛中的问题Kefa and Dishes,通过状压和spfa算法解决了这个问题。给定一个有向图,求在不超过m步的情况下,能获得的最大权值和。点不能重复走。文章详细介绍了问题的题意、解题思路和代码实现。 ... [详细]
  • Ihaveaworkfolderdirectory.我有一个工作文件夹目录。holderDir.glob(*)>holder[ProjectOne, ... [详细]
author-avatar
starry-night--_848
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有