Python 中的深度优先搜索算法(多个示例)

2023-10-22

深度优先搜索是一种流行的图遍历算法。在本教程中,我们将通过示例了解它的工作原理;以及我们如何用 Python 实现它。
我们将研究以下部分:

 

 

介绍

图和树是我们在计算机科学中的各种应用中使用的最重要的数据结构。
它们以节点的形式表示数据,节点通过“边”连接到其他节点。

与其他数据结构一样,遍历所有元素或在图或树中搜索元素是定义此类数据结构所需的基本操作之一。深度优先搜索就是这样一种图遍历算法。

深度优先搜索算法

深度优先搜索首先查看图的根节点(任意节点)。如果我们要遍历整个图,它会访问根节点的第一个子节点,然后依次查看该节点的第一个子节点,并继续沿着该分支,直到到达叶节点。

接下来,它以类似的方式回溯并探索父节点的其他子节点。这一直持续到我们访问了树的所有节点,并且没有任何父节点可供探索。

source: 维基百科

但是,如果我们正在执行特定元素的搜索,那么在每一步中,都会与我们当前所在的节点进行比较操作。
如果该元素不存在于特定节点中,则会发生探索每个分支和回溯的相同过程。

这一直持续到图的所有节点都被访问过,或者我们找到了我们正在寻找的元素。

 

表示一个图

在我们尝试用Python实现DFS算法之前,有必要首先了解如何在Python中表示图。

图表有多种版本。图可能具有两个节点之间的有向边(定义源和目的地)或无向边。节点之间的边可能有也可能没有权重。根据应用程序,我们可以使用图表的各种版本中的任何一个。

为了遍历整个图,我们将使用有向边的图(因为我们需要对节点之间的父子关系进行建模),并且边将没有权重,因为我们关心的是图的完整遍历。

现在,Python 有多种表示图的方法;两种最常见的方式如下:

  1. 邻接矩阵
  2. 邻接表

 

邻接矩阵

邻接矩阵是形状为 N x N 的方阵(其中 N 是图中的节点数)。
每行代表一个节点,每列代表该节点的潜在子节点。
每个(行,列)对代表一个潜在的边缘。

边是否存在取决于矩阵中相应位置的值。
(i,j) 位置处的非零值表示节点 i 和 j 之间存在边,而值为零表示 i 和 j 之间不存在边。

邻接矩阵中的值可以是二进制数或实数。
我们可以在非加权图中使用二进制值(1 表示存在边,0 表示不存在)。
对于实际值,我们可以将它们用于加权图,并表示与表示位置的行和列之间的边缘相关的权重。

例如,位置 (2,3) 处的值 10 表示节点 2 和 3 之间存在承载权重 10 的边。

在Python中,我们可以使用二维邻接矩阵来表示NumPy 数组.

 

邻接表

邻接表是多个列表的集合。每个列表代表图中的一个节点,并存储该节点的所有邻居/子节点。

在Python中,邻接列表可以使用字典来表示,其中键是图的节点,它们的值是存储这些节点的邻居的列表。

我们将使用这个表示来实现 DFS 算法。

让我们举一个示例图并使用 Python 中的字典来表示它。

给定的图有以下四个边:

  1. 甲->乙
  2. A -> C
  3. 乙 -> 丙
  4. C -> D

现在让我们用 Python 创建一个字典来表示这个图。


graph = {"A": ["B", "C"],
            "B": ["C"],
            "C": ["D"]}  

现在我们知道了如何在 Python 中表示图,我们可以继续实现 DFS 算法。

实现深度优先搜索(非递归方法)

我们将考虑第一部分动画中显示的图形示例。

让我们使用 Python 字典将此图定义为邻接表。


graph = {"A":["D","C","B"],
   "B":["E"],
   "C":["G","F"],
   "D":["H"],
   "E":["I"],
   "F":["J"]}  

使用 DFS 对该图进行遍历的预期顺序之一是:

让我们实现一个接受图并使用 DFS 遍历它的方法。我们可以使用递归技术以及非递归迭代方法来实现这一点。
在本节中,我们将研究迭代方法。

我们将使用堆栈和列表来跟踪访问过的节点。
我们将从根节点开始,将其附加到路径并将其标记为已访问。然后我们将其所有邻居添加到堆栈中。
在每一步中,我们都会从堆栈中弹出一个元素并检查它是否已被访问。
如果它还没有被访问过,我们会将它添加到路径中,并将其所有邻居添加到堆栈中。


def dfs_non_recursive(graph, source):
       if source is None or source not in graph:
           return "Invalid input"
       path = []
       stack = [source]
       while(len(stack) != 0):
           s = stack.pop()
           if s not in path:
               path.append(s)
           if s not in graph:
               #leaf node
               continue
           for neighbor in graph[s]:
               stack.append(neighbor)
       return " ".join(path)  

我们的用户定义方法将表示图的字典和源节点作为输入。
请注意,源节点必须是字典中的节点之一,否则该方法将返回“无效输入”错误。

让我们在定义的图上调用这个方法,并验证遍历的顺序是否与上图所示的一致。


DFS_path = dfs_non_recursive(graph, "A")
print(DFS_path)  

Output :

因此,图的遍历顺序是“深度优先”的方式。

 

使用递归方法的 DFS

我们可以使用一种称为递归的流行问题解决方法来实现深度优先搜索算法。

递归是一种将同一问题划分为更小的实例,并在其体内递归调用相同方法的技术。

我们将在我们的方法中定义一个基本情况,即“如果叶节点已被访问,我们需要回溯”。

我们来实现该方法:


def recursive_dfs(graph, source,path = []):
       if source not in path:
           path.append(source)
           if source not in graph:
               # leaf node, backtrack
               return path
           for neighbour in graph[source]:
               path = recursive_dfs(graph, neighbour, path)
       return path  

现在我们可以创建我们的图(与上一节相同),并调用递归方法。


graph = {"A":["B","C", "D"],
           "B":["E"],
           "C":["F","G"],
           "D":["H"],
           "E":["I"],
           "F":["J"]}
path = recursive_dfs(graph, "A")
print(" ".join(path))  

Output:

遍历的顺序还是深度优先的方式。

 

二叉树的深度优先搜索

什么是二叉树?

二叉树是一种特殊的图,其中每个节点只能有两个子节点或没有子节点。
二叉树的另一个重要属性是节点左子节点的值将小于或等于当前节点的值。
同样,右子节点的值大于当前节点的值。

因此,根节点左分支中的每个值都小于根处的值,而右分支中的每个值都将大于根处的值。

让我们了解如何使用 Python 类来表示二叉树。

 

使用 Python 类表示二叉树

我们可以创建一个类来表示树中的每个节点及其左右子节点。
使用根节点对象,我们可以解析整个树。

我们还将定义一个将新值插入二叉树的方法。


class Node:
       def __init__(self, value):
           self.value = value
           self.left = None
           self.right = None
       def insert(self, value):
           if value:
               if value < self.value:
                   if self.left is None:
                       self.left = Node(value)
                   else:
                       self.left.insert(value)
               elif value > self.value:
                   if self.right is None:
                       self.right = Node(value)
                   else:
                       self.right.insert(value)
               else:
                   self.value = value
  

现在让我们创建一个根节点对象并向其中插入值以构造一棵二叉树,如上一节中的图中所示。


root = Node(7)
root.insert(2)
root.insert(25)
root.insert(9)
root.insert(80)
root.insert(0)
root.insert(5)
root.insert(15)
root.insert(8)  

这将构建如上图所示的二叉树。
它还将确保无论我们以什么顺序插入值,都满足二叉树的属性,即“每个节点 2 个子节点”和“左

 

为二叉树实现 DFS

现在让我们定义一个递归函数,它将根节点作为输入,并按“深度优先搜索”顺序显示树中的所有值。


def dfs_binary_tree(root):
       if root is None:
           return
       else:
           print(root.value,end=" ")
           dfs_binary_tree(root.left)
           dfs_binary_tree(root.right)  

我们现在可以调用此方法并传递我们刚刚创建的根节点对象。


dfs_binary_tree(root)  

Output:

这种顺序也称为二叉树的“前序遍历”。

 

使用networkx进行深度优先搜索

到目前为止,我们一直在编写表示图和遍历图的逻辑。
但是,与所有其他重要应用程序一样,Python 也提供了一个处理图形的库。它被称为‘网络x’.

‘networkx’是一个Python包使用节点和边来表示图,并且它提供了多种方法对图执行不同的操作,包括 DFS 遍历。

我们首先看一下如何使用networkx构建一个图。

 

在networkx中构建图表

为了在networkx中构造一个图,我们首先创建一个图对象,然后使用“add_node()”方法添加图中的所有节点,然后使用“add_edge()”方法定义节点之间的所有边。

让我们使用“networkx”构建下图。


import networkx as nx
G = nx.Graph() #create a graph
G.add_node(1) # add single node
G.add_node(2)
G.add_node(3)
G.add_node(4)
G.add_node(5)
G.add_nodes_from([6,7,8,9]) #add multiple nodes  

现在我们已经添加了所有节点,让我们定义这些节点之间的边,如图所示。


# adding edges
G.add_edge(5,8)
G.add_edge(5,4)
G.add_edge(5,7)
G.add_edge(8,2)
G.add_edge(4,3)
G.add_edge(4,1)
G.add_edge(7,6)
G.add_edge(6,9)  

 

在 DFS 中可视化图形

现在,我们通过定义节点和边构建了图,让我们看看 networkx 的“draw()”方法看起来如何,并验证它是否按照我们想要的方式构建。我们将使用绘图库显示图表。


import matplotlib.pyplot as plt
nx.draw(G, with_labels=True, font_weight='bold')
plt.show()  

Output:

方向可能与我们的设计略有不同,但它类似于同一张图,节点之间以及节点之间具有相同的边。

现在让我们对该图执行 DFS 遍历。

 

Networkx 中的图遍历 – DFS

“networkx”提供了一系列以不同方式遍历图表的方法。我们将使用“dfs_preorder_nodes()”方法以深度优先搜索顺序解析图。

从图中预期的顺序应该是:
5、8、2、4、3、1、7、6、9

让我们调用该方法并查看它以什么顺序打印节点。


dfs_output = list(nx.dfs_preorder_nodes(G, source=5))
print(dfs_output)  

Output:

因此,networkx 的遍历顺序符合我们的预期。

现在我们已经很好地理解了深度优先搜索或 DFS 遍历,让我们看看它的一些应用。

 

使用深度优先搜索进行拓扑排序

拓扑排序是图的重要应用之一,用于对许多现实生活中的问题进行建模,其中任务的开始取决于其他任务的完成。

例如,我们可以使用图的节点来表示许多作业或任务。
某些任务可能依赖于某些其他任务的完成。这种依赖关系是通过建模的有向边节点之间。
具有有向边的图称为有向图。

如果我们想要从这样一组任务中执行调度操作,我们必须确保不违反依赖关系,即任务链中后面出现的任何任务始终仅在其之前的所有任务完成之后执行。
我们可以通过图的拓扑排序来实现这种顺序。

请注意,为了使拓扑排序成为可能,图中必须不存在有向循环,也就是说,该图必须是有向无环图or DAG.

让我们以 DAG 为例,并使用深度优先搜索方法对其执行拓扑排序。

假设上图中的每个节点代表工厂中生产产品的任务。节点模型之间的有向箭头是每个任务对先前任务完成的依赖关系。

因此,无论我们选择执行的任务顺序如何,为了开始任务 C,任务 A 和 E 必须已经完成。

类似地,为了执行任务I,任务A、E、C和F必须已经完成。由于节点 H 上没有向内的箭头,因此任务 H 可以在任何点执行,而不依赖于任何其他任务的完成。

我们可以使用 Python networkx 的“有向图”模块构建这样的有向图。


dag = nx.digraph.DiGraph()
dag.add_nodes_from(['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I'])
dag.add_edges_from([('A', 'B'), ('A', 'E'), ('B', 'D'), ('E', 'C'),
                      ('D', 'G'),('C', 'G'),('C', 'I'), ('F', 'I')])  

请注意,我们使用了方法“add_nodes_from()”和“add_edges_from()”一次性添加有向图的所有节点和边。

我们现在可以编写一个函数来使用 DFS 执行拓扑排序。

我们将从没有向内箭头的节点开始,并继续探索其分支之一,直到到达叶节点,然后回溯并探索其他分支。

一旦我们探索了一个节点的所有分支,我们就会将该节点标记为“已访问”并将其推送到堆栈中。

一旦访问了每个节点,我们就可以在堆栈上执行重复的弹出操作,以给出任务的拓扑排序顺序。

现在让我们将这个想法转化为一个Python函数:


def dfs(dag, start, visited, stack):
       if start in visited:
           # node and all its branches have been visited
           return stack, visited
       if dag.out_degree(start) == 0:
           # if leaf node, push and backtrack
           stack.append(start)
           visited.append(start)
           return stack, visited
       #traverse all the branches
       for node in dag.neighbors(start):
           if node in visited:
               continue
           stack, visited = dfs(dag, node, visited, stack)
       #now, push the node if not already visited
       if start not in visited:
           print("pushing %s"%start)
           stack.append(start)
           visited.append(start)
       return stack, visited
   def topological_sort_using_dfs(dag):
       visited = []
       stack=[]
       start_nodes = [i for i in dag.nodes if dag.in_degree(i)==0]
   #     print(start_nodes)
       for s in start_nodes:
           stack, visited = dfs(dag, s, visited, stack)
       print("Topological sorted:")
       while(len(stack)!=0):
           print(stack.pop(), end=" ")  

我们定义了两个函数,一个用于递归遍历节点,另一个主要的拓扑排序函数首先找到所有没有依赖关系的节点,然后使用深度优先搜索方法遍历每个节点。
最后,它从堆栈中弹出值,从而产生节点的拓扑排序。

现在我们调用函数“topological_sort_using_dfs()”


topological_sort_using_dfs(dag)  

Output :

如果我们仔细观察输出顺序,我们会发现每当每个作业启动时,它的所有依赖项都会在它之前完成。

我们还可以将其与“networkx”模块中名为“topological_sort()”的拓扑排序方法的输出进行比较。


topological_sorting = nx.topological_sort(dag)
for n in topological_sorting:
    print(n, end=' ')  

Output:

看起来 networkx 的 sort 方法产生的排序与我们的方法产生的排序相同。

 

使用 DFS 查找连通分量

图还有另一个重要的属性,称为连通分量。无向图中的连通分量是指一组节点,其中每个顶点通过路径连接到每个其他顶点。

让我们看下面的例子:

在上图中,存在三个连通分量;每个都被标记为粉红色。

让我们用 Python 构建这个图,然后制定一种在其中查找连接组件的方法。


graph = nx.Graph()
graph.add_nodes_from(['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I'])
graph.add_edges_from([('A', 'B'), ('B', 'E'), ('A', 'E')]) #component 1
graph.add_edges_from([('C', 'D'), ('D', 'H'), ('H', 'F'), ('F', 'C')]) #component 2
graph.add_edge('G','I') #component 3  

让我们同时想象一下它。


import matplotlib.pyplot as plt
nx.draw(graph, with_labels=True, font_weight='bold')
plt.show()  

Output:

为了使用 DFS 查找连通分量,我们将维护一个名为“visited”的通用全局数组,每次遇到尚未访问过的新变量时,我们都会开始查找它属于哪个连通分量。

我们将该组件中的每个节点标记为“已访问”,因此我们将无法重新访问它来查找另一个连接的组件。

我们将对每个节点重复此过程,调用 DFS 方法从节点查找连通分量的次数将等于图中连通分量的数量。

让我们用 Python 编写这个逻辑并在我们刚刚构建的图上运行它:


def find_connected_components(graph):
       visited = []
       connected_components = []
       for node in graph.nodes:
           if node not in visited:
               cc = [] #connected component
               visited, cc = dfs_traversal(graph, node, visited, cc)
               connected_components.append(cc)
       return connected_components
   def dfs_traversal(graph, start, visited, path):
       if start in visited:
           return visited, path
       visited.append(start)
       path.append(start)
       for node in graph.neighbors(start):
           visited, path = dfs_traversal(graph, node, visited, path)
       return visited, path  

让我们在上一步中构建的图表上使用我们的方法。


connected_components = find_connected_components(graph)
print("Total number of connected components =", len(connected_components))
for cc in connected_components:
    print(cc)  

Output:

 

结论

在这篇博客中,我们了解了 DFS 算法并以不同的方式使用它。

我们首先了解如何使用常见的数据结构来表示图,并在 Python 中实现它们。

然后,我们使用递归和非递归方法实现深度优先搜索遍历算法。

接下来,我们研究了一种称为二叉树的特殊形式的图,并在其上实现了 DFS 算法。
在这里,我们使用由我们定义的代表节点的 Python 类构造的节点对象来表示整个树。

然后我们研究了 Python 提供的用于表示图形并对其执行操作的产品——“networkx”模块。
我们用它来构建一个图,将其可视化,并在其上运行我们的 DFS 方法。我们将输出与模块自己的 DFS 遍历方法进行了比较。

最后,我们研究了深度优先搜索遍历的两个重要应用,即拓扑排序和查找图中的连通分量。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Python 中的深度优先搜索算法(多个示例) 的相关文章

  • 用于将 cython 中的许多 C++ 类包装到单个共享对象的项目结构

    我在文档 邮件列表和这个问题在这里 https stackoverflow com questions 10300660 cython and distutils 但我想得到一个更直接的答案来解决我的具体情况 我正在通过尝试一点一点地包装我
  • 没有名为 crypto.cipher 的模块

    我现在正在尝试加密一段时间 我最近得到了这个基于 python 的密码器 名为PythonCrypter https github com jbertman PythonCrypter 我对 Python 相当陌生 当我尝试通过终端打开 C
  • Python 中的 Lanczos 插值与 2D 图像

    我尝试重新缩放 2D 图像 灰度 图像大小为 256x256 所需输出为 224x224 像素值范围从 0 到 1300 我尝试了两种使用 Lanczos 插值来重新调整它们的方法 首先使用PIL图像 import numpy as np
  • Python 的键盘中断不会中止 Rust 函数 (PyO3)

    我有一个使用 PyO3 用 Rust 编写的 Python 库 它涉及一些昂贵的计算 单个函数调用最多需要 10 分钟 从 Python 调用时如何中止执行 Ctrl C 好像只有执行结束后才会处理 所以本质上没什么用 最小可重现示例 Ca
  • Django:按钮链接

    我是一名 Django 新手用户 尝试创建一个按钮 单击该按钮会链接到我网站中的另一个页面 我尝试了一些不同的例子 但似乎没有一个对我有用 举个例子 为什么这不起作用
  • Python - StatsModels、OLS 置信区间

    在 Statsmodels 中 我可以使用以下方法拟合我的模型 import statsmodels api as sm X np array 22000 13400 47600 7400 12000 32000 28000 31000 6
  • 如何替换 pandas 数据框列中的重音符号

    我有一个数据框dataSwiss其中包含瑞士城市的信息 我想用普通字母替换带有重音符号的字母 这就是我正在做的 dataSwiss Municipality dataSwiss Municipality str encode utf 8 d
  • Python pickle:腌制对象不等于源对象

    我认为这是预期的行为 但想检查一下 也许找出原因 因为我所做的研究结果是空白 我有一个函数可以提取数据 创建自定义类的新实例 然后将其附加到列表中 该类仅包含变量 然后 我使用协议 2 作为二进制文件将该列表腌制到文件中 稍后我重新运行脚本
  • OpenCV 无法从 MacBook Pro iSight 捕获

    几天后 我无法再从 opencv 应用程序内部打开我的 iSight 相机 cap cv2 VideoCapture 0 返回 并且cap isOpened 回报true 然而 cap grab 刚刚返回false 有任何想法吗 示例代码
  • Python 函数可以从作用域之外赋予新属性吗?

    我不知道你可以这样做 def tom print tom s locals locals def dick z print z name z name z guest Harry print z guest z guest print di
  • AWS EMR Spark Python 日志记录

    我正在 AWS EMR 上运行一个非常简单的 Spark 作业 但似乎无法从我的脚本中获取任何日志输出 我尝试过打印到 stderr from pyspark import SparkContext import sys if name m
  • Flask如何获取请求的HTTP_ORIGIN

    我想用我自己设置的 Access Control Allow Origin 标头做出响应 而弄清楚请求中的 HTTP ORIGIN 参数在哪里似乎很混乱 我在用着烧瓶 0 10 1 以及HTTP ORIGIN似乎是这个的特点之一object
  • Python 的“zip”内置函数的 Ruby 等价物是什么?

    Ruby 是否有与 Python 内置函数等效的东西zip功能 如果不是 做同样事情的简洁方法是什么 一些背景信息 当我试图找到一种干净的方法来进行涉及两个数组的检查时 出现了这个问题 如果我有zip 我可以写这样的东西 zip a b a
  • Pygame:有没有简单的方法可以找到按下的任何字母数字的字母/数字?

    我目前正在开发的游戏需要让人们以自己的名义在高分板上计时 我对如何处理按键有点熟悉 但我只处理过寻找特定的按键 有没有一种简单的方法可以按下任意键的字母 而不必执行以下操作 for event in pygame event get if
  • 解释 Python 中的数字范围

    在 Pylons Web 应用程序中 我需要获取一个字符串 例如 关于如何做到这一点有什么建议吗 我是 Python 新手 我还没有找到任何可以帮助解决此类问题的东西 该列表将是 1 2 3 45 46 48 49 50 51 77 使用
  • 有没有办法检测正在运行的代码是否正在上下文管理器内执行?

    正如标题所述 有没有办法做到这样的事情 def call back if called inside context print running in context else print called outside context 这将
  • 如何计算 pandas 数据帧上的连续有序值

    我试图从给定的数据帧中获取连续 0 值的最大计数 其中包含来自 pandas 数据帧的 id date value 列 如下所示 id date value 354 2019 03 01 0 354 2019 03 02 0 354 201
  • Rocket UniData/UniVerse:ODBC 无法分配足够的内存

    每当我尝试使用pyodbc连接到 Rocket UniData UniVerse 数据时我不断遇到错误 pyodbc Error 00000 00000 Rocket U2 U2ODBC 0302810 Unable to allocate
  • 导入错误:没有名为 site 的模块 - mac

    我已经有这个问题几个月了 每次我想获取一个新的 python 包并使用它时 我都会在终端中收到此错误 ImportError No module named site 我不知道为什么会出现这个错误 实际上 我无法使用任何新软件包 因为每次我
  • Statsmodels.formula.api OLS不显示截距的统计值

    我正在运行以下源代码 import statsmodels formula api as sm Add one column of ones for the intercept term X np append arr np ones 50

随机推荐

  • 如何在 Ubuntu 20.04 中安装 PostgreSQL 和 pgAdmin4

    PostgreSQL是一个强大 可靠 健壮且开源的对象关系数据库系统 该数据库系统的最新版本是 PostgreSQL 13 2 而版本 12 6 11 11 10 16 9 6 21 和 9 5 25 仍在定期更新 本教程介绍如何在 Ubu
  • 如何在 Ubuntu 和 Debian 中切换 Python 版本

    Python 是一种高级编程语言 广泛用于系统编程 它适用于所有流行的操作系统 您可以在单个系统上安装多个 Python 版本 安装多个 Python 版本后 您可以使用 update alternatives 工具切换默认 Python
  • 如何在 CentOS 7 上安装和使用 Docker

    Docker 是一种容器化技术 可让您快速构建 测试和部署应用程序 作为可移植 自给自足的容器 几乎可以在任何地方运行 在本教程中 我们将介绍如何在 CentOS 7 上安装 Docker CE 并探索基本的 Docker 概念和命令 先决
  • 如何在 CentOS 8 上安装 CouchDB

    Apache CouchDB 是由 Apache 软件基金会开发的免费开源 NoSQL 数据库 它可以用作单节点或集群数据库 CouchDB 服务器将其数据存储在命名数据库中 其中包含具有以下内容的文档JSON结构 每个文档由许多字段和附件
  • 如何在 Ubuntu 20.04 上安装 Kvm

    KVM 基于内核的虚拟机 是内置于 Linux 内核中的开源虚拟化技术 使用 KVM 运行多个 Linux 或 Windows 来宾虚拟机 每个来宾都与其他来宾完全隔离 并拥有自己的操作系统和专用虚拟硬件 例如 CPU 内存 网络接口和存储
  • 如何在 Ubuntu 20.04 上安装 OpenCV

    OpenCV 开源计算机视觉库 是一个开源计算机视觉库 绑定了 C Python 和 Java 并支持所有主要操作系统 它可以利用多核处理并具有 GPU 加速功能来实现实时操作 OpenCV 的应用范围很广 包括医学图像分析 拼接街景图像
  • 如何在 Debian 10 Linux 上添加交换空间

    交换空间是磁盘上的空间 当物理内存已满时使用 当 Linux 系统耗尽 RAM 时 非活动页面将从 RAM 移至交换空间 交换空间可以采用专用交换分区或交换文件的形式 通常 运行 Debian 虚拟机时不存在交换分区 因此唯一的选择是创建交
  • 如何在 CentOS 8 上安装 Apache Maven

    Apache Maven 是一个开源项目管理和理解工具 主要用于 Java 项目 Maven 使用项目对象模型 POM 它本质上是一个 XML 文件 其中包含有关项目 配置详细信息 项目依赖项等的信息 在本教程中 我们将解释如何在 Cent
  • 如何在 Ubuntu 18.04 上安装 TensorFlow

    TensorFlow是由 Google 构建的免费开源机器学习平台 许多组织都在使用它 包括 Twitter PayPal 英特尔 联想和空中客车公司 TensorFlow 可以在 Python 虚拟环境中安装在系统范围内 作为Docker
  • Linux 中的 Chattr 命令(文件属性)

    在 Linux 中 文件属性是描述文件行为的元数据属性 例如 属性可以指示文件是否被压缩或指定文件是否可以被删除 一些属性 如不变性 可以设置或清除 而其他属性 如加密 是只读的 只能查看 对某些属性的支持取决于所使用的文件系统 本文介绍了
  • 在Ubuntu上安装RPM包

    Ubuntu 存储库包含数千个 deb 软件包 可以从 Ubuntu 软件中心或使用apt命令行实用程序 Deb 是所有基于 Debian 的发行版 包括 Ubuntu 都使用的安装包格式 有些软件包在标准 Ubuntu 存储库中不可用 但
  • 如何检查PHP版本

    PHP 是最常用的服务器端编程语言之一 PHP 版本之间存在一些重要差异 因此在某些情况下可能需要了解您的服务器上运行的是哪个版本 例如 如果您在开始安装之前升级应用程序或安装需要特定 PHP 版本的新应用程序 则需要找出 PHP 服务器的
  • 如何在 Debian 10 Linux 上安装 Google Chrome 网络浏览器

    谷歌浏览器是世界上最流行的网络浏览器 它是专为现代网络打造的快速 直观且安全的浏览器 Chrome 不是开源浏览器 并且不包含在官方 Debian 存储库中 它是基于Chromium 一个开源浏览器 可在默认 Debian Buster 存
  • 如何在 Ubuntu 中将用户添加到 Sudoers

    sudo是一个命令行程序 允许受信任的用户以 root 或其他用户身份执行命令 在本文中 我们将向您展示两种向用户授予 sudo 权限的方法 第一个是将用户添加到sudoers 文件 该文件包含控制向哪些用户和组授予 sudo 权限以及权限
  • 检查 gzip 文件而不解压缩:zcat、zless 和 zmore

    Linux 提供了多个用于处理压缩文件的命令 例如 zcat zless 和 zmore 本教程将深入探讨这些命令的用法 让您可以导航和检查压缩文件 而无需解压缩它们 下表总结了这 3 种工具之间的差异 Tool Description P
  • 使用 source 命令在 Linux 中获取脚本

    The sourceLinux 中的 command 是一个内置的 shell 命令 用于从文件中读取和执行命令 这意味着脚本定义的任何变量或函数在脚本执行完成后仍然可用 现在 让我们开始探索它的功能source命令 目录 hide 1 子
  • Linux 上的 MySQL(初学者教程)

    在这篇文章中 我们将介绍 Linux 上 MySQL 的许多方面 首先 如何安装它 如何执行基本的 CRUD 操作 如何导入和导出数据 如何使用 MySQL 引擎本身 例如设置 root 用户密码 等等 MySQL 是世界上最流行的关系数据
  • 将 NumPy 数组转换为 Pandas DataFrame(15+ 场景)

    通常我们需要在 NumPy 数组中创建数据并将其转换为 DataFrame 因为我们必须处理 Pandas 方法 在这种情况下 转换NumPy 数组 ndarrays 到数据框使我们的数据分析变得方便 在本教程中 我们将仔细研究一些可用于将
  • 使用 Python 发送电子邮件(多个示例)

    Python 允许您使用其内置模块自动执行发送电子邮件的任务 这样做可以让您摆脱手动向数千名用户发送电子邮件的繁琐且耗时的任务 本教程将探讨一些快速 简单的发送电子邮件和使用 Python 内置电子邮件模块的方法 目录 hide 1 检查电
  • Python 中的深度优先搜索算法(多个示例)

    深度优先搜索是一种流行的图遍历算法 在本教程中 我们将通过示例了解它的工作原理 以及我们如何用 Python 实现它 我们将研究以下部分 目录 hide 1 介绍 2 深度优先搜索算法 3 Representing a graph