图论:图的遍历(DFS vs. BFS)

news2024/9/20 18:36:03

文章目录

    • 引言
    • 基本概念
      • 无向图示例
      • 绘制图形
    • 深度优先搜索(DFS)
      • 基本概念
      • 可视化 DFS 过程
      • 深度优先搜索(DFS)
      • DFS 应用场景
    • 广度优先搜索(BFS)
      • 基本概念
      • 可视化 BFS 过程
      • 广度优先搜索(BFS)
      • 应用场景
    • DFS vs. BFS
      • 基本概念对比
      • 性能对比
      • 场景分析
      • **总结对比**
    • 社交网络图遍历
      • 使用 DFS
      • 使用 BFS
    • 结语

引言

图的遍历是图论中的核心概念,通过不同的遍历方法能够有效地处理多种问题,例如连通性检测、路径查找、图的最小生成树等。本篇我们将重点探讨图的深度优先搜索(DFS)和广度优先搜索(BFS)两种常见的图遍历方法,分析它们的原理、应用场景以及实现方法,并通过实际案例代码分析问题解决方案。

在这里插入图片描述

基本概念

图是一种表示对象间关系的数据结构,由顶点和边组成。按照边的方向,图可以分为有向图和无向图。图的遍历主要有两种方式:

  • 深度优先搜索(DFS):优先深入图的分支,直到无法继续时回溯。
  • 广度优先搜索(BFS):优先探索与当前节点相邻的节点,然后逐层向外扩展。

无向图示例

下面是一个无向图示例,适合用于探讨图的遍历(深度优先搜索和广度优先搜索)。

    A
   / \
  B  C
 /|  |
D |  |
 \|  |
  E--F
  |  |
  G  H
   \ |
    I

在这个图中,节点的连接关系如下:

  • A 连接 B、C
  • B 连接 D、E
  • C 连接 E、F
  • D 连接 E
  • E 连接 G、F
  • F 连接 H
  • G 连接 I
  • H 连接 I

绘制图形

下面的代码使用 networkxmatplotlib 库绘制该图。请确保已安装这两个库(如果尚未安装,请运行 pip install networkx matplotlib)。

以下是绘制上述无向图的 Python 代码:

import matplotlib.pyplot as plt
import networkx as nx

# 创建空图
G = nx.Graph()

# 添加节点和边
edges = [
    ('A', 'B'),
    ('A', 'C'),
    ('B', 'D'),
    ('B', 'E'),
    ('C', 'E'),
    ('C', 'F'),
    ('D', 'E'),
    ('E', 'F'),
    ('E', 'G'),
    ('F', 'H'),
    ('G', 'I'),
    ('H', 'I')
]

G.add_edges_from(edges)

# 绘制图形
pos = nx.spring_layout(G)  # 选择布局
nx.draw(G, pos, with_labels=True, node_color='lightblue', node_size=700, font_size=12, font_weight='bold', edge_color='gray')

# 显示图形
plt.title("无向图示例")
plt.show()

运行上述代码将生成一个表示上述无向图的可视化图形,为后续对深度优先搜索(DFS)和广度优先搜索(BFS)的探讨提供一个演示基础。

在这里插入图片描述

代码释意

  • 导入库:使用 matplotlib.pyplot 来绘制图形,使用 networkx 来处理图结构。
  • 创建图:创建一个无向图对象 G
  • 添加边:通过 add_edges_from 方法将边添加到图中,定义节点之间的连接关系。
  • 设置图的布局:使用 spring_layout 选择图形的布局,这有助于更清晰地展示图的结构。
  • 绘制图形:使用 nx.draw 来绘制图,设置节点的颜色、大小和标签。
  • 显示图:通过 plt.show() 来显示绘制的图形。

深度优先搜索(DFS)

基本概念

深度优先搜索利用栈(可以用递归实现)来访问图中的节点。当访问一个节点时,会深度探索该节点的所有相邻节点,直到无法继续。

算法步骤

  1. 从起始节点开始,标记为已访问。
  2. 递归访问未访问的相邻节点。
  3. 如果所有相邻节点都已访问,回溯到上一个节点。

下面我们将逐步展示如何使用 Python 代码演示无向图的深度优先搜索(DFS)过程与效果吗,并实现 DFS 算法。

可视化 DFS 过程

在实现 DFS 并打印结果后,我们可以通过 matplotlib 绘制这幅图以可视化 DFS 的遍历过程。为了展示仍然在访问中的节点,我们将在访问每个节点时更新图像。

以下是完整的 DFS 过程可视化实现:

import matplotlib.pyplot as plt
import networkx as nx
import time

class Graph:
    def __init__(self):
        self.graph = nx.Graph()  # 使用 networkx 的 Graph 对象

    def add_edge(self, u, v):
        self.graph.add_edge(u, v)  # 直接添加边到 Graph 对象

    def dfs(self, start):
        visited = set()
        path = []
        self._dfs_util(start, visited, path)
        return path

    def _dfs_util(self, vertex, visited, path):
        visited.add(vertex)
        path.append(vertex)  # 记录路径
        self.visualize_dfs(path)  # 可视化图遍历
        for neighbor in self.graph[vertex]:  # 使用 networkx 的方式访问相邻节点
            if neighbor not in visited:
                self._dfs_util(neighbor, visited, path)

    def visualize_dfs(self, path):
        plt.clf()  # 清空当前的图
        pos = nx.spring_layout(self.graph)
        nx.draw(self.graph, pos, with_labels=True, node_color='lightblue', node_size=700, font_size=12, font_weight='bold', edge_color='gray')
        # 着色已访问的节点
        nx.draw_networkx_nodes(self.graph, pos, nodelist=path, node_color='orange')
        plt.title("深度优先搜索(DFS)可视化")
        plt.pause(0.5)  # 暂停以绘制图像


# 创建无向图
G = Graph()
edges = [
    ('A', 'B'), ('A', 'C'), ('B', 'D'), ('B', 'E'),
    ('C', 'E'), ('C', 'F'), ('D', 'E'), ('E', 'F'),
    ('E', 'G'), ('F', 'H'), ('G', 'I'), ('H', 'I')
]

for u, v in edges:
    G.add_edge(u, v)

# 设置图的布局
plt.ion()  # 开启交互模式
plt.figure(figsize=(8, 6))

# 执行 DFS
dfs_result = G.dfs('A')
print("深度优先搜索的结果:", dfs_result)

plt.ioff()  # 关闭交互模式
plt.show()  # 显示最终图
# 深度优先搜索的结果: ['A', 'B', 'D', 'E', 'C', 'F', 'H', 'I', 'G']

代码释意

  • 图的构建:使用 add_edge 方法构建无向图,确保每个节点都相互连接。
  • DFS 实现:使用递归方法进行深度优先搜索,同时在每次访问节点时调用可视化函数。
  • 可视化函数:使用 matplotlib 不断更新图的显示,以展示各个节点的遍历状态。
  • 交互模式:通过开启交互模式(plt.ion()),允许我们逐步更新图。

运行示例

运行上面的完整代码,可以看到图的遍历过程。每次访问一个节点时,节点将会变为橙色,表示已访问。最终,程序也会打印出 DFS 的结果路径。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

深度优先搜索的结果: ['A', 'B', 'D', 'E', 'C', 'F', 'H', 'I', 'G']

深度优先搜索(DFS)

下面是 DFS 算法的实现。我们使用一个递归方法进行实现,在访问每个节点时记录路径,以便可视化图遍历结果。

import matplotlib.pyplot as plt
import networkx as nx

class Graph:
    def __init__(self):
        self.graph = {}

    def add_edge(self, u, v):
        if u not in self.graph:
            self.graph[u] = []
        if v not in self.graph:
            self.graph[v] = []
        self.graph[u].append(v)
        self.graph[v].append(u)  # 无向图,双向添加

    def dfs(self, start):
        visited = set()
        path = []
        self._dfs_util(start, visited, path)
        return path

    def _dfs_util(self, vertex, visited, path):
        visited.add(vertex)
        path.append(vertex)  # 记录路径
        for neighbor in self.graph.get(vertex, []):
            if neighbor not in visited:
                self._dfs_util(neighbor, visited, path)

# 创建无向图
G = Graph()
edges = [
    ('A', 'B'), ('A', 'C'), ('B', 'D'), ('B', 'E'),
    ('C', 'E'), ('C', 'F'), ('D', 'E'), ('E', 'F'),
    ('E', 'G'), ('F', 'H'), ('G', 'I'), ('H', 'I')
]

for u, v in edges:
    G.add_edge(u, v)

# 执行 DFS
dfs_result = G.dfs('A')
print("深度优先搜索的结果:", dfs_result)
# 深度优先搜索的结果: ['A', 'B', 'D', 'E', 'C', 'F', 'H', 'I', 'G']

关键点

  • 递归深度:DFS 的递归深度可能导致栈溢出,特别是在具有深层嵌套的图上。可考虑使用显式栈来替代递归。
  • 访问状态:使用集合来管理访问状态,提高查询效率。

DFS 应用场景

  • 连通性检测:判断图中是否存在连接路径。
  • 图的遍历:访问图中的所有节点。
  • 找出图中的环:通过深度优先遍历可以判断图中是否存在环。
  • 路径查找:在特定情况下寻找从起点到终点的路径。

广度优先搜索(BFS)

基本概念

广度优先搜索利用队列来逐层访问图中的节点。首先访问起始节点,然后将所有直接相邻的节点入队,并继续出队和访问这些节点。

算法步骤

  1. 从起始节点开始,将其加入队列并标记为已访问。
  2. 循环直到队列为空,出队当前节点,并访问其相邻节点。
  3. 将未访问的相邻节点入队并标记为已访问。

我们逐步展示如何使用 Python 代码演示无向图的广度优先搜索(BFS)过程与效果,以及实现 BFS 算法。

可视化 BFS 过程

以下是使用队列实现 BFS,访问每个节点时记录路径,以及可视化图遍历结果。

import matplotlib.pyplot as plt
import networkx as nx
from collections import deque

class Graph:
    def __init__(self):
        self.graph = nx.Graph()  # 使用 networkx 的 Graph 对象

    def add_edge(self, u, v):
        self.graph.add_edge(u, v)  # 直接添加边到 Graph 对象

    def bfs(self, start):
        visited = set()
        path = []
        queue = deque([start])  # 使用 deque 作为队列

        while queue:
            vertex = queue.popleft()
            if vertex not in visited:
                visited.add(vertex)
                path.append(vertex)  # 记录路径
                self.visualize_bfs(path)  # 可视化图遍历
                for neighbor in self.graph[vertex]:
                    if neighbor not in visited:
                        queue.append(neighbor)  # 将未访问的相邻节点加入队列

        return path

    def visualize_bfs(self, path):
        plt.clf()  # 清空当前的图
        pos = nx.spring_layout(self.graph)
        nx.draw(self.graph, pos, with_labels=True, node_color='lightblue', node_size=700, font_size=12, font_weight='bold', edge_color='gray')
        # 着色已访问的节点
        nx.draw_networkx_nodes(self.graph, pos, nodelist=path, node_color='orange')
        plt.title("广度优先搜索(BFS)可视化")
        plt.pause(0.5)  # 暂停以绘制图像

# 创建无向图
G = Graph()
edges = [
    ('A', 'B'), ('A', 'C'), ('B', 'D'), ('B', 'E'),
    ('C', 'E'), ('C', 'F'), ('D', 'E'), ('E', 'F'),
    ('E', 'G'), ('F', 'H'), ('G', 'I'), ('H', 'I')
]

for u, v in edges:
    G.add_edge(u, v)

# 设置图的布局
plt.ion()  # 开启交互模式
plt.figure(figsize=(8, 6))

# 执行 BFS
bfs_result = G.bfs('A')
print("广度优先搜索的结果:", bfs_result)

plt.ioff()  # 关闭交互模式
plt.show()  # 显示最终图

代码释意

  • Graph 类
    • 使用 nx.Graph() 创建无向图。
    • add_edge(u, v) 方法将边添加到图中。
  • 广度优先搜索(BFS)
    • bfs(start) 方法使用队列(deque)遍历图。
    • 访问每个节点时,将其添加到路径中,并调用 visualize_bfs() 方法进行图的可视化。
  • 可视化方法
    • visualize_bfs(path) 方法清空图并重新绘制,只标记已访问的节点。
    • 使用 plt.pause(0.5) 使图的更新可见。

运行示例

运行上述代码后,将看到一个窗口,展示 BFS 的遍历过程。每次访问一个节点时,该节点会变为橙色,同时终端将打印 BFS 的结果路径。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

广度优先搜索的结果: ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I']

广度优先搜索(BFS)

以下是 BFS 的实现示例:

from collections import deque

class Graph:
    def __init__(self):
        self.graph = {}

    def add_edge(self, u, v):
        if u not in self.graph:
            self.graph[u] = []
        self.graph[u].append(v)

    def bfs(self, start):
        visited = set()
        queue = deque([start])
        visited.add(start)

        while queue:
            vertex = queue.popleft()
            print(vertex)  # 处理节点
            for neighbor in self.graph.get(vertex, []):
                if neighbor not in visited:
                    visited.add(neighbor)
                    queue.append(neighbor)

# 示例
g = Graph()
g.add_edge(0, 1)
g.add_edge(0, 2)
g.add_edge(1, 3)
g.add_edge(1, 4)
g.add_edge(2, 5)

print("广度优先搜索(BFS)结果:")
g.bfs(0)
# 广度优先搜索(BFS)结果:
# 0
# 1
# 2
# 3
# 4
# 5

关键点

  • 队列管理:使用双端队列(deque)提高入队和出队效率。
  • 内存消耗:BFS 可能在大图上消耗更多的内存,以存储队列和访问状态。

应用场景

  • 最短路径查找:在无权图中,BFS 可找到从源节点到其他节点的最短路径。
  • 网络广播:在网络中实现信息传播。
  • 连通分量的寻找:用于找出不同的连通区域。

DFS vs. BFS

深度优先搜索(DFS)和广度优先搜索(BFS)是图遍历的两种基本算法,各自具有独特的特点和应用场景。

基本概念对比

DFS 尽可能深地搜索图的分支,直到该分支末端才会进行回溯。可以基于递归或显式栈来实现。沿着一条路径走到尽头,再回退到最近的分支。

BFS 按层次逐层扩展,同一层的节点会在深入下一层之前全部访问。使用队列来实现。首先访问起点的所有直接邻居,然后依次访问每个邻居的邻居,直到所有节点被访问。

性能对比

  • 时间复杂度
    • DFS:$O(V + E) $, V V V 是顶点数, E E E 是边数。
    • BFS: O ( V + E ) O(V + E) O(V+E),同样的复杂度。
  • 空间复杂度
    • DFS:最坏情况下为 O ( h ) O(h) O(h) h h h 是树的高度(对于深度较大的图可能会出现栈溢出)。
    • BFS:最坏情况下为 O ( V ) O(V) O(V),因为可能需要存储所有节点。

场景分析

深度优先搜索(DFS)

  • 应用领域
    • 图的连通性检测:DFS 可以用来检测图是否连通,或找到图的连通分量。
    • 路径查找:适合查找从起点到终点的任意路径(不是最短路径)。
    • 拓扑排序:在有向无环图(DAG)中进行拓扑排序。
    • 拼图游戏:如八数码问题、迷宫求解等可以使用 DFS 来尝试不同路径。
  • 场景示例
    • 迷宫探索:在迷宫中寻找一条通向出口的路径,DFS 可以快速深入复杂的路径。
    • 网络爬虫:在网页链接中递归访问,直到没有未访问的链接。

广度优先搜索(BFS)

  • 应用领域
    • 最短路径查找:BFS 可以在无权图中找到从起点到终点的最短路径。
    • 层次遍历:适合在树或图中进行层次遍历,获取节点的层级信息。
    • 网络广播:在传播消息或数据时使用 BFS,有助于确保信息的快速扩散。
  • 具体示例
    • 社交网络分析:在社交网络中查找用户之间的最短连接。
    • 路径规划:如地图中的最短路径规划,帮助导航。

总结对比

特点深度优先搜索(DFS)广度优先搜索(BFS)
主要策略深度优先,不回头层次优先
实现方式递归或栈队列
应用场景路径搜索、拓扑排序、迷宫最短路径、网络传播
时间复杂度 O ( V + E ) O(V + E) O(V+E) O ( V + E ) O(V + E) O(V+E)
空间复杂度 O ( h ) O(h) O(h) O ( V ) O(V) O(V)

在实际问题中,根据具体需求选择最合适的算法:如果需求是查找最短路径,尤其是在无权图中,选择 BFS。如果需要探索所有可能的路径或解决递归问题,使用 DFS。选择合适的遍历方法能提高解决问题的效率和有效性。

社交网络图遍历

假设在一个社交网络中,我们想要找到从用户 A 出发能到达的所有用户,并且希望探索社交网络的至少一层。

  • 输入:用户 A 的 ID, 一个社交网络图。
  • 目标:获取从用户 A 出发的所有直接联系人和关系。

我们可以针对这个问题分别使用 DFS 和 BFS。

使用 DFS

# DFS 实现
g = Graph()
g.add_edge('A', 'B')
g.add_edge('A', 'C')
g.add_edge('B', 'D')
g.add_edge('B', 'E')
g.add_edge('C', 'F')

print("DFS 结果:")
g.dfs('A')

输出将是:

A
B
D
E
C
F

使用 BFS

# BFS 实现
g = Graph()
g.add_edge('A', 'B')
g.add_edge('A', 'C')
g.add_edge('B', 'D')
g.add_edge('B', 'E')
g.add_edge('C', 'F')

print("BFS 结果:")
g.bfs('A')

输出将是:

A
B
C
D
E
F

结语

通过深度优先搜索(DFS)和广度优先搜索(BFS)两种图遍历方法,我们能够有效地解决多种图论问题。根据不同需求选择正确的遍历方式,当需要寻找图中的所有路径或连通分量时,或处理树结构上的递归问题时,DFS 是一个不错的选择。而当需要寻找最短路径或进行层次遍历时,BFS 是更好的选择。

在实际应用中,评估图的特性和需求,从而选择最合适的遍历方法是极其重要的。此外,应合理管理内存使用,避免栈溢出和内存消耗过高等问题。


PS:感谢每一位志同道合者的阅读,欢迎关注、点赞、评论!


  • 上一篇:图论:配对问题与匈牙利算法
  • 专栏:「数智通识」

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

有效三角形个数问题

目录 一题目简述: 二思路总结: 21不被认可的暴力破解思路: 22优化后的思路: 221优化后的判断三角形方法: 222 定一动二指针朝内筛选遍历: 三解答代码: 一题目简述: leetcode链…

500以内有好用的开放式耳机推荐吗?五款500以内开放式耳机推荐

作为一个几乎醒了就离不开耳机的人,我经常在思考什么样子的耳机才能做到佩戴无感、不塞耳、没有胀痛,还可以随时为我们提供高品质音乐呢?划拉来,划拉去还是觉得开放式耳机比较适合,它不入耳的设计能够让空气在耳朵流通…

基于大模型 + 知识库的 Code Review 实践

背景 💡 想法源于在一次 Code Review 时,向 Claude 询问哪种写法代码更优雅得来。当时就想能不能让 AI 帮我们辅助做 Code Review? 痛点 信息安全合规问题:公司内代码直接调 ChatGPT / Claude 会有安全/合规问题,为了…

HR招聘,如何解决面试流程繁琐的问题

要解决面试流程繁琐的问题,就必须要精简和优化招聘流程。比如精简面试环节,制定标准化流程,完善信息管理,对面试环节进行细致梳理之后,尽快识别并去除那些不必要的步骤,这样就能够减少求职者的等待时间&…

零成本搭建个人 APP 和小程序后台

前言 前面也说了,通过 GitHub PagesGitHub Actions 只是解决了动态数据展示,但是要零成本得完成将用户信息存储下来,并实现数据交互呢? 我开始是想用云文档,种种原因,我还是希望有个自己能二次修改的后台…

动态网格交易、科创板做市、股票 CTA……DolphinDB 中高频策略回测实例之股票篇

股票中高频交易是量化交易的重要分支,其核心在于在极短时间内处理大量市场数据,执行多笔交易,从而捕捉细微的价格波动并获取利润。中高频交易策略的成功依赖于精准的算法设计、低延迟的交易系统以及交易程序强大的数据分析能力。作为实盘操作…

【系统架构设计】设计模式

【系统架构设计】设计模式 设计模式概述GoF设计模式Factory MethodAbstract Factory (*)BuilderPrototype(原型)Singleton(*)AdapterBridgeComposite(组合)Decorator(装饰)(*)Facade(外观)(*&am…

恢复指定人微信聊天记录,看这里,4种方法帮您找回记录

微信在今天成为了我们日常生活中不可或缺的一部分,它承载着我们的社交、工作乃至生活的点点滴滴。然而,有时出于各种原因,我们可能会选择注销微信账号,但随后又可能因种种原因希望恢复其微信进行使用。那么,微信注销了…

CSS溢出——WEB开发系列20

在网页设计中,“溢出”是一个常见且重要的概念。它涉及到如何处理那些超出预定范围的内容,以确保网页的布局和视觉效果达到预期。 一、什么是溢出? 在 CSS 中,“溢出”(overflow)指的是内容超出其包含块的…

构建高效NLP管道:PydanticOutputParser与Langchain的结合

PydanticOutputParser 是一个用于解析语言模型输出的实用工具,它允许用户指定一个 Pydantic 模型,并查询语言模型以生成符合该模型的 JSON 输出。这个工具特别有用,因为它可以帮助开发者确保从语言模型获得的结构化数据符合预期的格式&#x…

全面解析:四大LLM模型——预训练与后训练的新范式

导读 最初,大语言模型LLM的训练过程只关注于预训练,但如今已经扩展到包含预训练和后训练两个阶段。后训练通常包括监督指令微调和对齐,这一方法在ChatGPT发布后广泛流行! 翻译自:https://magazine.sebastianraschka.com/p/new-l…

NAT网关产品手册

产品用途 SG-NAT-410 网关支持 IP 地址跨网段和通讯端口的转换,为不方便修改参数的以太网通讯设备的信息化联网提供便捷的解决方案。网关有 1 个两口以太网交换机接口(LAN 口 ) 和 1 个单口以太网通讯接口 (WAN 口 ) 。不对原系统做任何硬件和软件修改&…

WAF一般是怎么防御SQL注入的

目录 参数化查询在防止SQL注入中起到什么作用? 为什么要限制数据库用户权限来预防SQL注入? WAF是如何检测SQL注入特征的? WAF防范SQL注入的主要策略包括: 参数化查询和预编译语句:使用参数化查询或预编译语句可以确…

虚拟试穿技术分享

虚拟试穿技术,通过计算机视觉和人工智能,允许用户在数字界面上试穿服装,无需实际穿戴。这项技术广泛应用于电子商务和时尚工业,使得消费者可以在购买前预览衣物在自己身上的样子。 基于扩散的方法:这种方法使用基于图像…

微波网络分析仪VNA原理详解:电磁波测量基础-测试狗科研测试

微波网络分析仪VNA原理详解:电磁波测量基础 微波网络分析仪(Vector Network Analyzer,简称VNA)是一种用于测试和测量微波频段元件和网络特性的电子测试设备。 一、电磁波 电磁波是由电场和磁场相互垂直并相互依赖振荡传播的波动现…

餐饮商标怎么注册自己的品牌!

餐饮行业是创业者选的比较多的行业,也有许多人从小做起,成为当地知名品牌,那企业或个体户如何注册餐饮行业的商标。 在餐饮行业首先是申请注册类别43类餐饮住宿,这个是餐饮的核心类别,开店、饭店都在这个类别&#xf…

学习之adb命令

adb命令作用: 用来操作手机系统的 类似于window的cmd,linux的bash 如果添加环境变量的adb不能识别设备通常是因为存在两个不同的版本 如下: adb devices 如果没有发现,可以尝试手动连接设备 需要先执行 adb kill-server adb start-server …

前端模块自动导入的插件

前言 开发中通常会有很多导入语句&#xff0c;如何确保一些通用的api和hook无需每次手动导入即可使用。 <script setup lang"ts"> import { ref, reactive } from "vue" import { useRoute, useRouter } from "vue-router" import { log…

【Spring】Cookie和Session

系列文章目录 第一章 初识Spring MVC 文章目录 系列文章目录前言一、Cookie和Session二、Cookie操作获取Cookie指定Cookie 三、Session操作设置Session数据获取Session数据 四、获取Header总结 前言 HTTP是"无状态"的协议&#xff0c;我们可以理解为它没有记忆力。…

UnrealEngine学习(02):虚幻引擎编辑器界面详解

学习一款软件&#xff0c;我个人建议是先学习怎么用&#xff0c;然后是学习怎么用的好&#xff0c;再研究源码。 上一篇文章详细描述了我们该如何安装虚幻5引擎&#xff1a; UnrealEngine学习(01)&#xff1a;安装虚幻引擎https://blog.csdn.net/zuodingquan666/article/deta…