【生物信息学算法】图算法1:概念和算法

文章目录

    • 1. 图的定义、分类、表达方式
      • 图的定义
      • 图的分类
      • 表达方式
      • Python实现
    • 2.相邻节点和度
      • 概念定义
      • python实现
    • 3.路径、距离和搜索
      • 路径和距离
      • 搜索
    • 4.图论中的欧拉定理

1. 图的定义、分类、表达方式

图的定义

图G可以由两个集合来定义,即G=(V,E)。其中,V是对象的集合,称为图的顶点或节点; E是V中(u,v)顶点对的集合,称为边或弧,表示u和v之间的关系存在。

图的分类

  1. 有向图:E有方向性,即顶点对是有序的。
  2. 无向图:E无方向性,即顶点对是无序的。
  3. 加权图:对E中的边赋予数值权重。

表达方式

图形,邻接矩阵,邻接列表

·邻接矩阵:行列表示图的节点;矩阵中的具体数值,在无权图中主要表示是否存在该边(以及该边的方向),在加权图中则会包含权重的信息
·当图是稀疏时,使用基于邻接列表的实现存储更有效

Python实现

class MyGraph:# 定义图的类def __init__(self, g={}):'''构造函数,接受一个字典作为输入来填充图的结构;默认为一个空字典。:param g: 图的初始结构,默认为空字典'''self.graph = g# 获取图的基本信息def get_nodes(self):'''获取图中的所有节点(顶点)。:return: 节点列表'''return list(self.graph.keys())def get_edges(self):'''获取图中的所有边。:return: 边的列表,列表中的每个元素是一个元组,表示两个相连的节点'''edges = []# 遍历所有节点for v in self.graph.keys():# 遍历每个节点的邻接列表for d in self.graph[v]:# 将每条边(节点对)添加到边列表中edges.append((v, d))return edgesdef size(self):'''返回图的节点数和边数。:return: 一个元组,包含节点数和边数'''return len(self.get_nodes()), len(self.get_edges())def print_graph(self):'''打印图的邻接列表表示法。每个节点及其相邻节点列表都会输出。'''for v in self.graph.keys():print(v, " -> ", self.graph[v])def add_vertex(self, v):'''向图中添加一个新的节点(顶点)。如果节点已存在,则不添加。:param v: 要添加的节点'''if v not in self.graph.keys():self.graph[v] = []def add_edge(self, o, d):'''向图中添加一条新的边。如果边的两个节点(顶点)不存在,则会自动添加这些节点。:param o: 边的起始节点:param d: 边的目标节点'''# 如果起始节点不存在,则添加该节点if o not in self.graph.keys():self.add_vertex(o)# 如果目标节点不存在,则添加该节点if d not in self.graph.keys():self.add_vertex(d)# 如果目标节点不在起始节点的邻接列表中,则添加该边if d not in self.graph[o]:self.graph[o].append(d)

2.相邻节点和度

概念定义

有向图G=(V,E)中,若边的集合E中存在有序对(s,v),则顶点v是顶点s的后继(successor),s称为v的前身;两个顶点s和v被命名为邻接,即如果一个顶点是另一个顶点的后继,则两个顶点是邻接的。

节点度给定节点的相邻节点数,在有向图中:入度为计算一个节点的前置数出度为一个节点的后继数

python实现

接上

    def get_successors(self, v):'''获取节点v的所有后继节点(邻接节点)。返回v的邻接列表的副本,避免列表被覆盖。:param v: 节点:return: 节点v的所有后继节点的列表'''return list(self.graph[v])  # 返回节点v的邻接列表的副本,避免原列表被修改def get_predecessors(self, v):'''获取图中所有指向节点v的前驱节点。:param v: 节点:return: 节点v的所有前驱节点的列表'''res = []  # 用于存储前驱节点的列表# 遍历所有节点,检查它们的邻接列表for k in self.graph.keys():if v in self.graph[k]:  # 如果节点v在节点k的邻接列表中,说明k是v的前驱节点res.append(k)return resdef get_adjacents(self, v):'''获取与节点v相连的所有相邻节点,包括前驱和后继。:param v: 节点:return: 节点v的所有相邻节点的列表'''suc = self.get_successors(v)  # 获取v的后继节点pred = self.get_predecessors(v)  # 获取v的前驱节点res = pred  # 将前驱节点列表赋值给res# 检查所有后继节点,如果它们不在前驱节点列表中,则添加到结果列表中for p in suc:if p not in res:res.append(p)return resdef out_degree(self, v):'''计算节点v的出度(从该节点出发的边的数量)。:param v: 节点:return: 节点v的出度'''return len(self.graph[v])  # 节点v的邻接列表的长度即为出度def in_degree(self, v):'''计算节点v的入度(指向该节点的边的数量)。:param v: 节点:return: 节点v的入度'''return len(self.get_predecessors(v))  # 前驱节点的数量即为入度def degree(self, v):'''计算节点v的度数(与该节点相连的边的数量,包括入度和出度)。:param v: 节点:return: 节点v的度数'''return len(self.get_adjacents(v))  # 相邻节点的数量即为度数def all_degrees(self, deg_type="inout"):'''计算所有节点的度数(入度、出度或总度数)。:param deg_type: 度数类型,可以是 "in"(入度)、"out"(出度)或 "inout"(总度数):return: 一个字典,键是节点,值是对应的度数'''degs = {}  # 创建一个空字典用于存储每个节点的度数# 遍历所有节点,计算出度或总度数for v in self.graph.keys():# 如果度数类型是出度("out")或总度数("inout")if deg_type == "out" or deg_type == "inout":degs[v] = len(self.graph[v])  # 节点v的出度是其邻接列表的长度else:degs[v] = 0  # 如果不是计算出度,初始化为0# 遍历所有节点,计算入度或总度数if deg_type == "in" or deg_type == "inout":for v in self.graph.keys():# 遍历节点v的邻接节点for d in self.graph[v]:# 如果度数类型是入度("in")或者v不在d的邻接列表中(避免重复计算)if deg_type == "in" or v not in self.graph[d]:degs[d] = degs[d] + 1  # 对应节点的度数加1return degs  # 返回包含所有节点度数的字典

3.路径、距离和搜索

路径和距离

路径(path):在有向图中,定义为节点的有序列表,其中列表中的连续节点需要通过边连接。即这个过程中的每一步都是从一个节点沿着图中的一条“边”走到另一个节点。所以路径就是这些节点的有序排列。

在图 G=(V, E) 中:

  • 有向图中,节点 x 和任意节点 y 之间的路径 P 是列表 P = p 1 , p 2 , … , p n P = p_1, p_2, \ldots, p_n P=p1,p2,,pn,其中 p 1 = x p_1 = x p1=x, p n = y p_n = y pn=y,以及 P P P 上的所有连续节点对 ( p i , p i + 1 ) ∈ E (p_i, p_{i+1}) \in E (pi,pi+1)E 。即路径上的每一对相邻节点 p i , p i + 1 p_i, p_{i+1} pi,pi+1 都必须是有向边集合 E E E 中的一条边。
  • 无向图中,则 ( p i , p i + 1 ) ∈ E (p_i, p_{i+1}) \in E (pi,pi+1)E ( p i + 1 , p i ) ∈ E (p_{i+1}, p_i) \in E (pi+1,pi)E
    最短路径:两个节点之间边数最少的路径,最短路径的长度称为两点间的距离
    代码实现:
    def distance(self, s, d):'''计算从节点s到节点d的最短路径的距离(使用广度优先搜索算法)。:param s: 起始节点:param d: 目标节点:return: 从s到d的最短距离,如果没有路径返回None'''if s == d:  # 如果起始节点等于目标节点,距离为0return 0l = [(s, 0)]  # 初始化队列l,包含起始节点和初始距离0visited = [s]  # 初始化已访问列表,包含起始节点# 当队列不为空时,继续搜索while len(l) > 0:node, dist = l.pop(0)  # 弹出队列的第一个元素,获取当前节点和当前距离# 遍历当前节点的邻接节点for elem in self.graph[node]:if elem == d:  # 如果找到目标节点,返回距离加1return dist + 1elif elem not in visited:  # 如果邻接节点未访问过l.append((elem, dist + 1))  # 将邻接节点加入队列,距离加1visited.append(elem)  # 标记邻接节点为已访问return None  # 如果没有找到路径,返回Nonedef shortest_path(self, s, d):'''查找从节点s到节点d的最短路径(使用广度优先搜索算法)。:param s: 起始节点:param d: 目标节点:return: 从s到d的最短路径(节点列表),如果没有路径返回None'''if s == d:  # 如果起始节点等于目标节点,返回空路径return 0l = [(s, [])]  # 初始化队列l,包含起始节点和初始路径(空列表)visited = [s]  # 初始化已访问列表,包含起始节点# 当队列不为空时,继续搜索while len(l) > 0:node, preds = l.pop(0)  # 弹出队列的第一个元素,获取当前节点和路径# 遍历当前节点的邻接节点for elem in self.graph[node]:if elem == d:  # 如果找到目标节点,返回完整路径return preds + [node, elem]elif elem not in visited:  # 如果邻接节点未访问过l.append((elem, preds + [node]))  # 将邻接节点加入队列,更新路径visited.append(elem)  # 标记邻接节点为已访问return None  # 如果没有找到路径,返回None

搜索

广度优先搜索(BFS):从源节点开始,然后访问其所有后续节点,然后访问这些后续节点的后续节点直到访问所有可能的节点
深度优先搜索(DFS):从源节点开始,先搜索第一个后继节点,然后再搜索其第一个后继节点直到无法进行进一步的搜索,然后回溯以探索其他替代方案

代码实现:

    def reachable_bfs(self, v):'''使用广度优先搜索(BFS)算法找到从节点v可以到达的所有节点。:param v: 起始节点:return: 从v可以到达的所有节点的列表'''l = [v]  # 初始化列表l,包含起始节点v,作为搜索队列res = []  # 初始化结果列表,用于存储已访问的节点# 当搜索队列不为空时,继续搜索while len(l) > 0:node = l.pop(0)  # 取出队列的第一个节点# 如果节点不是起始节点,添加到结果列表if node != v:res.append(node)# 遍历当前节点的所有邻接节点for elem in self.graph[node]:# 如果邻接节点不在结果列表和搜索队列中,加入队列if elem not in res and elem not in l:l.append(elem)return res  # 返回所有从节点v可以到达的节点def reachable_dfs(self, v):'''使用深度优先搜索(DFS)算法找到从节点v可以到达的所有节点。:param v: 起始节点:return: 从v可以到达的所有节点的列表'''l = [v]  # 初始化列表l,包含起始节点v,作为搜索堆栈res = []  # 初始化结果列表,用于存储已访问的节点# 当搜索堆栈不为空时,继续搜索while len(l) > 0:node = l.pop(0)  # 取出堆栈的第一个节点# 如果节点不是起始节点,添加到结果列表if node != v:res.append(node)s = 0  # 位置变量,用于控制新元素插入的位置(保持DFS的堆栈顺序)# 遍历当前节点的所有邻接节点for elem in self.graph[node]:# 如果邻接节点不在结果列表和搜索堆栈中,插入堆栈顶部if elem not in res and elem not in l:l.insert(s, elem)  # 在索引s的位置插入元素s += 1  # 更新位置变量return res  # 返回所有从节点v可以到达的节点

·如果一条路径在同一个顶点上开始和结束,则该路径被定义为闭合的
·如果在闭合路径中没有重复的节点或边,则该路径称为。(主要为了排除两个节点间的一来一回)
代码实现:

def node_has_cycle(self, v):'''检查从给定节点v开始的图中是否存在环(使用广度优先搜索算法)。:param v: 起始节点:return: 如果存在环,返回True;否则返回False'''l = [v]  # 初始化队列l,包含起始节点vres = False  # 初始化结果为False,表示暂未发现环visited = [v]  # 初始化已访问列表,包含起始节点v# 当队列不为空时,继续搜索while len(l) > 0:node = l.pop(0)  # 弹出队列的第一个元素,获取当前节点# 遍历当前节点的所有邻接节点for elem in self.graph[node]:if elem == v:  # 如果邻接节点等于起始节点,说明存在环return Trueelif elem not in visited:  # 如果邻接节点未访问过l.append(elem)  # 将邻接节点加入队列visited.append(elem)  # 标记邻接节点为已访问return res  # 如果没有发现环,返回Falsedef has_cycle(self):'''测试图中是否存在环(从任意节点开始)。:return: 如果存在环,返回True;否则返回False'''res = False  # 初始化结果为False,表示暂未发现环# 遍历所有节点,测试每个节点是否是环的起点for v in self.graph.keys():if self.node_has_cycle(v):  # 如果从节点v开始存在环return Truereturn res  # 如果没有发现环,返回False

4.图论中的欧拉定理

欧拉迹(欧拉路径):在图论中,欧拉迹是指一条经过图中所有边且恰好一次的路径。这条路径可以重复访问顶点,但不能重复访问边。
欧拉回路:在图论中,欧拉回路指的是一种通过图中所有边恰好一次,并且最终回到起点的闭合路径
连通图:如果图中的任意两个顶点之间都有路径相连,那么这个图被称为连通图。换句话说,连通图是一个没有孤立部分的图,图中的所有顶点都是相互可达的。
欧拉定理连通图存在欧拉迹当且仅当图中奇度数的点的个数至多为 2

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/418764.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

STM32 HAL CAN通讯 实操

1、简介 相比于串口通讯,对于刚接触CAN通讯的小白来说,CAN通讯相对复杂,看各种视频、帖子理论,总是一知半解。本次通过傻瓜式操作,先实现CAN通讯的交互,以提高小白的信心,也便于自己复习观看。本次以STM32CubeMX进行初始化配置,通过Keil 5软件进行软件设计,通过CAN盒…

远心镜头选型公式

在当今的机器视觉领域,远心镜头凭借其独特的远心光路设计以及超低畸变、高远心度和高景深等特点,成为尺寸测量和视觉对位中的得力工具。然而,如何进行快速而准确的选型呢?答案就在于选型公式:倍率 焦距 N.A.Sensor 尺…

[linux 驱动]platform总线设备驱动详解与实战

目录 1 描述 2 结构体 2.1 bus_type 2.2 platform_bus_type 2.2.1 platform_match 2.2.2 platform_uevent 2.2.3 platform_dma_configure 2.2.4 platform_dev_pm_ops 2.3 platform_driver 2.4 platform_device 3 platform注册 3.1 platform_driver_register 3.1.1 …

springblade-JWT认证缺陷漏洞CVE-2021-44910

漏洞成因 SpringBlade前端通过webpack打包发布的,可以从其中找到app.js获取大量接口 然后直接访问接口:api/blade-log/api/list 直接搜索“请求未授权”,定位到认证文件:springblade/gateway/filter/AuthFilter.java 后面的代码…

el-table使用type=“expand”根据数据条件隐藏展开按钮

一&#xff1a;添加className <el-table :data"tableData" border :loading"loading" :row-class-name"getRowClass" expand-change"expandchange"><el-table-column type"expand"><template #default"…

爬虫基础知识+豆瓣电影实战

什么是爬虫 简单来说&#xff0c;爬虫就是获取网页并提取和保存信息的自动化程序&#xff0c;爬虫能够自动请求网页&#xff0c;并将所需要的数据抓取下来。通过对抓取的数据进行处理&#xff0c;从而提取出有价值的信息进行存储使用。 为什么用Python做爬虫 首先您应该…

Java创建线程(5种方法)

操作系统提供api操作线程 线程本身是操作系统提供的&#xff0c;操作系统提供API让我们操作线程&#xff0c;JVM对操作系统api进行了封装&#xff0c;在线程这一部分&#xff0c;就提供了Thread类&#xff0c;表示线程。 创建线程 创建一个MyThread类&#xff08;类的名字不…

六、Maven依赖管理、依赖传递和依赖冲突

1.Maven依赖管理 Maven 依赖管理是 Maven 软件中最重要的功能之一。Maven 的依赖管理能够帮助开发人员自动解决软件包依赖问题&#xff0c;使得开发人员能够轻松地将其他开发人员开发的模块或第三方框架集成到自己的应用程序或模块中&#xff0c;避免出现版本冲突和依赖缺失等…

Open Source, Open Life 第九届中国开源年会论坛征集正式启动

中国开源年会 COSCon 是业界最具影响力的开源盛会之一&#xff0c;由开源社在2015年首次发起&#xff0c;而今年我们将迎来第九届 COSCon&#xff01; 以其独特定位及日益增加的影响力&#xff0c;COSCon 吸引了越来越多的国内外企业、高校、开源组织/社区的大力支持。与一般企…

centos7使用ifconfig查看IP,终端无ens33信息解决办法

1.问题描述 大概有十几天没用虚拟机&#xff0c;最后一次用忘记关闭虚拟机系统了&#xff1b;突然&#xff0c;发现我用远程连接工具&#xff0c;连接不上&#xff0c;去到虚拟机内部查看IP发现终端竟然没有输出enss33地址信息&#xff0c;额&#xff0c;就像下面这样。 2.解决…

50Kg大载重长航时无人机技术详解

1. 机体结构设计 针对50Kg级大载重长航时无人机的设计&#xff0c;机体结构需兼顾轻量化、高强度与高稳定性。通常采用复合材料&#xff08;如碳纤维、玻璃纤维等&#xff09;作为主体材料&#xff0c;这些材料不仅重量轻&#xff0c;而且具有良好的抗疲劳性和耐腐蚀性&#x…

ARP协议(原理,特点,报文格式,具体过程),ARP缓存(有效时间,为什么),ARP欺骗(定向断网,成为中间人),RARP简单介绍

目录 ARP协议 引入 介绍 原理 arp请求/响应 特点 报文格式 硬件类型 协议类型 硬件/协议地址长度 op(操作码) 过程 发送请求并处理 返回响应并处理 总结 arp缓存 介绍 arp表项的有效时间 解释 arp欺骗 介绍 定向断网 基于arp的成为中间人的方式 多向…

0基础学习爬虫系列:Python环境搭建

1.背景 当前网络资源更新非常快&#xff0c;然后对应自己感兴趣的内容&#xff0c;每天盯着刷网站又太费时间。我在尝试借助Ai&#xff0c;搭建一套自己知识抓取更新提醒的系统&#xff0c;这样可以用极少的时间&#xff0c;关注到自己感兴趣的信息。 其实&#xff0c;这套逻辑…

使用 Python 实现粒子群优化的理论与实践

这是关于 PSO 是什么以及如何使用它的教程 欢迎来到雲闪世界。有一个笑话让我笑翻了&#xff1a; “您知道吗&#xff0c;在时钟发明之前&#xff0c;人们必须主动四处走动并询问时间&#xff1f;” 显然&#xff0c;这个笑话无需解释&#xff0c;但如果我们稍微思考一下&…

IOS17.0安装巨魔:TrollRestore巨魔发布

&#x1f47b; TrollRestore 17.0 巨魔发布 15.0 - 16.7 RC&#xff08;20H18&#xff09;和17.0。 官网&#xff1a;https://trollrestore.com/ 下载&#xff1a;https://pan.metanetdisk.com/IOS/%E5%B7%A8%E9%AD%94%E7%8E%A9%E5%AE%B6/TrollRestore.com 使用&#xff1a;ht…

共享单车轨迹数据分析:以厦门市共享单车数据为例(一)

共享单车数据作为交通大数据的一个重要组成部分&#xff0c;在现代城市交通管理和规划中发挥着越来越重要的作用。通过对共享单车的数据进行深入分析&#xff0c;城市管理者和规划者能够获得大量有价值的洞察&#xff0c;这些洞察不仅有助于了解城市居民的日常出行模式&#xf…

希尔排序/选择排序

前言&#xff1a; 本篇主要对常见的排序算法进行简要分析&#xff0c;代码中均以数组 arr[] { 5, 3, 9, 6, 2, 4, 7, 1, 8 } 为例&#xff0c;进行升序排列。 常见的排序算法有如下&#xff1a; 选择排序中&#xff0c;直接选择排序没有任何实际与教育意义&#xff0c;而堆排…

基于Python爬虫的淘宝服装数据分析项目

文章目录 一.项目介绍二.爬虫代码代码分析 三. 数据处理四. 数据可视化 一.项目介绍 该项目是基于Python爬虫的淘宝服装数据分析项目&#xff0c;以致于帮助商家了解当前服装市场的需求&#xff0c;制定更加精确的营销策略。首先&#xff0c;需要爬取淘宝中关于服装的大量数据…

人工智能训练师边缘计算实训室解决方案

一、引言 随着物联网&#xff08;IoT&#xff09;、大数据、人工智能&#xff08;AI&#xff09;等技术的飞速发展&#xff0c;计算需求日益复杂和多样化。传统的云计算模式虽在一定程度上满足了这些需求&#xff0c;但在处理海量数据、保障实时性与安全性、提升计算效率等方面…

MyBatis-SQL-语句执行流程

已查询为例 首先我们可以看到&#xff0c;在查询的时候Mapper对象已经是被代理过后的&#xff1a; 所以会执行invoke方法&#xff0c;其底层实现就是JDK的动态代理&#xff1a; 如下图所示&#xff0c;如果MethodCache里面存在方法&#xff0c;则判断这个方法是否为default方…