当前位置: 首页 > news >正文

Timsort 算法

文章目录

    • 1 基础理解
      • 1.1 定义和原理
      • 1.2 工作原理
    • 2 算法实现
      • 2.1 Python 代码实现
        • 2.1.1 代码
        • 2.1.2 核心逻辑
          • 计算最小运行长度(calc_min_run(n))
          • 插入排序(insertion_sort(arr, left, right))
      • 2.2 Java 代码实现
      • 2.3 C 代码实现
    • 3 逻辑细节
      • 3.1 如何选择合适的 min_run?
      • 3.2 如何处理边界情况?例如数组长度小于 min_run
    • 4 性能和优化细节
      • 4.1 为什么 Timsort 比纯归并排序或插入排序更高效?
      • 4.2 Timsort 在不同数据分布下的性能表现如何?
        • (1)完全随机的数据
        • (2)部分有序的数据
        • (3)已经排序的数据
      • 4.3 如何根据实际需求调整 Timsort 的参数以优化性能?
        • (1)大规模数据排序
        • (2)性能敏感的排序任务
      • 4.4 改进方向

1 基础理解

1.1 定义和原理

Timsort 算法是一种 稳定的 混合排序算法,结合了归并、插入排序的优点,利用了数组中已存在的有序序列(run)来提高排序效率。对小规模数据用插入排序,大规模数据用归并排序。平均时间复杂度为 O(nlogn),适合处理部分有序的数据。

Python 的内置排序函数 sorted() 和列表的 sort() 方法底层使用了 Timsort。

1.2 工作原理

  1. 先将数组划分为多个有序子数组run,每个run是一个非递减或非递增的连续子序列,Timsort 会自动检测这些 run,若一个 run 是递减的,则将其反转为递增的。

    如 [3, 4, 3, 2, 1, 7, 8, 9],检测到以下 run:[3, 4](递增)[3, 2, 1](递减,反转后为 [1, 2, 3])[7, 8, 9](递增)
    
  2. 计算一个最小 run 长度 minrun,一般在 [32,64] 区间中取值,具体取决于数组总长。若某个 run 长度小于 minrun,则用 插入排序 将其扩展到 至少 minrun 的长度

    如长为 100 的数组,minrun 可能被设置为 32。
    若检测到一个长为 10 的 run,则用插入排序将其扩展到至少 32 个元素
    
  3. 归并排序:若所有 run 的长度均满足要求,则将这些 run 做二路归并,其中,Timsort 使用 galloping mode 归并策略

     Galloping Mode:二路归并中,若出现连续的“一边倒”情况 —— 一个 run 的元素 连续多次小于 另一个 run 的元素),Timsort 会切换到 galloping mode。这种模式下,算法会以指数级的速度跳过元素,从而减少不必要的比较。
    
  4. 归并时,Timsort 用 临时数组 存中间结果。为减少内存开销,Timsort 会预分配一个足够大的临时数组,在归并途中复用这个数组。

2 算法实现

2.1 Python 代码实现

2.1.1 代码
#python 做升序排序MIN_MERGE = 32def calc_min_run(n):"""计算最小的运行长度(run)"""r = 0while n >= MIN_MERGE:r |= n & 1 n >>= 1 return n + rdef insertion_sort(arr, left, right):"""插入排序"""for i in range(left + 1, right + 1):key = arr[i]j = i - 1while j >= left and arr[j] > key:arr[j + 1] = arr[j]j -= 1arr[j + 1] = keydef merge(arr, l, m, r):"""合并两个有序数组"""len1, len2 = m - l + 1, r - mleft, right = [], []for i in range(len1):left.append(arr[l + i])for i in range(len2):right.append(arr[m + 1 + i])i, j, k = 0, 0, lwhile i < len1 and j < len2:if left[i] <= right[j]:arr[k] = left[i]i += 1else:arr[k] = right[j]j += 1k += 1while i < len1:arr[k] = left[i]i += 1k += 1while j < len2:arr[k] = right[j]j += 1k += 1def timsort(arr):n = len(arr)min_run = calc_min_run(n)# 对每个小块进行插入排序for start in range(0, n, min_run):end = min(start + min_run - 1, n - 1)insertion_sort(arr, start, end)# 合并有序块size = min_runwhile size < n:for left in range(0, n, size * 2):mid = min(n - 1, left + size - 1)right = min((left + 2 * size - 1), (n - 1))if mid < right:merge(arr, left, mid, right)size *= 2# 示例
if __name__ == "__main__":arr = [5, 9, 1, 3, 4, 6, 6, 3, 2]print("原始数组:", arr)timsort(arr)print("排序后数组:", arr)
2.1.2 核心逻辑
计算最小运行长度(calc_min_run(n))

目的:确定每个小块的最小长度(min run),用于后续的插入排序。
性能优化:通过 位运算 高效计算 min_run,避免复杂的数学运算

MIN_MERGE = 32def calc_min_run(n):r = 0while n >= MIN_MERGE:r |= n & 1n >>= 1return n + r

逻辑解释:

  1. 初始设定 MIN_MERGE = 32,表示每个小块的最小长度通常至少为 32。

  2. r 变量(0、1 两种取法)用于累积 n 的最低位,确保最终的 min_run 能够在一定范围内动态调整。

  3. 通过位运算(n >>= 1 和 r |= n & 1),逐步将 n 右移并累积最低位,直到 n 小于 MIN_MERGE。

  4. 最终返回 n + r,这确保了 min_run 的值在合理范围内,同时考虑了数组长度的具体情况。

    补充:1、n&1 按位与(同1为1,其他为0):若 n = 5 = 101B,则 101 & 001 = 001,n&1=1若 n = 4 = 100B,则 100 & 001 = 000,n&1=0总结:n&1 结果取决于 n 的二进制最低位,若最低位是1,结果为1;若最低位是0,结果为0。2、r |= ... :按位或赋值,r 与 后面表达式 进行按位或运算,并将结果赋值给 r3、按位或(至少一个为1时,结果为1,其他都是0 —— 有1为1,其他为0):若 r = 0,n & 1 = 1,则 r |= n & 1 ,使 r 变为 1若 r = 0,n & 1 = 0,则 r |= n & 1, 使 r 变为 04、‌>> 是 按位右移运算符n >>= 1 :n 的二进制向右移一位,等效于 n除以2(取整)
    

综上,这段代码的做法就是:将数组总长 n,不断的除 2 取整 ,直至 n < MIN_MERGE,最终返回这个 n 与 r (0 或 1) 的加和。

插入排序(insertion_sort(arr, left, right))

目的:对数组的某个子区间 [left, right] 进行插入排序。

性能优化:插入排序在小规模数据上效率很高,且实现简单,时间复杂度为 O(n²),部分有序时效率较高。通过直接在原数组上操作,避免额外的内存开销。

def insertion_sort(arr, left, right):""" 插入排序: 设 arr[left] 是已排部分的第一个元素,则从 left + 1 起处理未排序部分的元素。 """#从 left + 1 开始遍历到 rightfor i in range(left + 1, right + 1):key = arr[i]#从当前元素的前一个位置开始,向前遍历已排序部分j = i - 1#arr[j]大于当前元素key,则 arr[j] 后移一位while j >= left and arr[j] > key:arr[j + 1] = arr[j]j -= 1 arr[j + 1] = key 

逻辑解释:

  1. 从 left + 1 开始遍历到 right,将每个元素 key 插入到已排序部分的合适位置。
  2. 内层循环将大于 key 的元素依次向后移动,为 key 腾出插入位置。

例如,对如下数组中索引为 [0,15] 的子序列做插入排序(小白请看,糕手略过):

索 引0123456131415
数组值5724310986

这放个图,方便对照
在这里插入图片描述

第 1 轮 insertion_sort(arr, left, right):insertion_sort(arr, 0, 15) ——for i in range(1, 16) :遍历数组中索引为 [1,15] 的元素第 1 轮 for 循环 —— " i = 1 "key = arr[i] : arr[1] = 7 —— key 即当前元素 arr[1]j = i - 1 :j = 0 —— 当前元素的前一个元素索引 jwhile j >= left and arr[j] > key :第 1 轮 判断 0 >= 0 and arr[0] > 7 因 arr[0] = 5 < key = 7,故跳过 while,执行后面arr[j + 1] = key : arr[1] = key = 7—— 当前元素 arr[i] = arr[1] = 7 与前一个元素 arr[i-1] = arr[0] = 5 符合升序排序,所以,没进 while 循环,j 未变动,后面的 arr[j + 1] = key 相当于未进行操作。第 2 轮 for 循环 —— " i = 2 " : 后移判断下一个元素,当前元素 arr[i] 即 arr[2]key = arr[i] : arr[2] = 2 —— key 即当前元素 arr[2]j = i - 1 :j = 1 —— 当前元素的前一个元素索引 jwhile j >= left and arr[j] > key:第 1 轮 判断 " 1 >= 0 and arr[1] = 7 > 2 " —— 前一个 > 当前这个,进循环体arr[j + 1] = arr[j] :arr[2] = arr[1] ——  前一个元素 赋到 当前位置,达到大数后移的升序目的(当前位置 arr[j+1] 和前一个位置 arr[j] 都是这个大的数)j -= 1 :j = 0 —— 索引 j 前移 1 位第 2 轮 进 while ,做条件判断 " 0 >= 0 and arr[0] = 5 > 2先去吃个饭,下午再写

2.2 Java 代码实现

//java
import java.util.Arrays;public class TimSort {private static final int MIN_MERGE = 32;public static void timSort(int[] arr) {int n = arr.length;for (int i = 0; i < n; i += MIN_MERGE) {insertionSort(arr, i, Math.min((i + MIN_MERGE - 1), (n - 1)));}for (int size = MIN_MERGE; size < n; size = 2 * size) {for (int left = 0; left < n; left += 2 * size) {int mid = left + size - 1;int right = Math.min((left + 2 * size - 1), (n - 1));if (mid < right) {merge(arr, left, mid, right);}}}}private static void insertionSort(int[] arr, int left, int right) {for (int i = left + 1; i <= right; i++) {int temp = arr[i];int j = i - 1;while (j >= left && arr[j] > temp) {arr[j + 1] = arr[j];j--;}arr[j + 1] = temp;}}private static void merge(int[] arr, int left, int mid, int right) {int[] leftArray = Arrays.copyOfRange(arr, left, mid + 1);int[] rightArray = Arrays.copyOfRange(arr, mid + 1, right + 1);int i = 0, j = 0, k = left;while (i < leftArray.length && j < rightArray.length) {if (leftArray[i] <= rightArray[j]) {arr[k++] = leftArray[i++];} else {arr[k++] = rightArray[j++];}}while (i < leftArray.length) {arr[k++] = leftArray[i++];}while (j < rightArray.length) {arr[k++] = rightArray[j++];}}public static void main(String[] args) {int[] arr = {5, 3, 1, 4, 6, 2};timSort(arr);System.out.println("Sorted array using Tim Sort: " + Arrays.toString(arr));}
}

2.3 C 代码实现

//C
#include <stdio.h>
#include <stdlib.h>
#include <string.h>#define MIN_MERGE 32void insertionSort(int arr[], int left, int right) {for (int i = left + 1; i <= right; i++) {int temp = arr[i];int j = i - 1;while (j >= left && arr[j] > temp) {arr[j + 1] = arr[j];j--;}arr[j + 1] = temp;}
}void merge(int arr[], int left, int mid, int right) {int n1 = mid - left + 1;int n2 = right - mid;int L[n1], R[n2];memcpy(L, arr + left, n1 * sizeof(int));memcpy(R, arr + mid + 1, n2 * sizeof(int));int i = 0, j = 0, k = left;while (i < n1 && j < n2) {if (L[i] <= R[j]) {arr[k++] = L[i++];} else {arr[k++] = R[j++];}}while (i < n1) {arr[k++] = L[i++];}while (j < n2) {arr[k++] = R[j++];}
}void timSort(int arr[], int n) {for (int i = 0; i < n; i += MIN_MERGE) {insertionSort(arr, i, (i + MIN_MERGE - 1) < (n - 1) ? (i + MIN_MERGE - 1) : (n - 1));}for (int size = MIN_MERGE; size < n; size = 2 * size) {for (int left = 0; left < n; left += 2 * size) {int mid = left + size - 1;int right = (left + 2 * size - 1) < (n - 1) ? (left + 2 * size - 1) : (n - 1);if (mid < right) {merge(arr, left, mid, right);}}}
}int main() {int arr[] = {5, 3, 1, 4, 6, 2};int n = sizeof(arr) / sizeof(arr[0]);timSort(arr, n);printf("Sorted array using Tim Sort: ");for (int i = 0; i < n; i++) {printf("%d ", arr[i]);}printf("\n");return 0;
}

3 逻辑细节

3.1 如何选择合适的 min_run?

参数 min_run 决定了数组被分割成 多大的小块 进行插入排序。

通常,min_run 的值在 32 到 64 之间。Python 的 Timsort 实现中,默认值是 32。

min_run 的值可以这样计算(能根据数组长,动态调整):

#python
MIN_MERGE = 32def calc_min_run(n):"""计算最小的运行长度(run)"""r = 0while n >= MIN_MERGE:r |= n & 1 # 0、1 两种取值n >>= 1 # n/2 取整return n + r

3.2 如何处理边界情况?例如数组长度小于 min_run

若 数组长 < min_run,可直接对整个数组进行插入排序。因为插入排序在小规模数据上的性能很好,而且实现简单。

#python
if len(arr) < min_run:insertion_sort(arr, 0, len(arr) - 1)

4 性能和优化细节

4.1 为什么 Timsort 比纯归并排序或插入排序更高效?

  • Timsort 结合了两种排序算法的优点:

     插入排序:在小规模数据上效率很高,且实现简单。归并排序:在大规模数据上效率很高,且稳定。
    
  • 利用了自然有序序列
    Timsort 能识别数组中已存在的有序序列(run),并利用其减少归并次数和复杂度。这使 Timsort 在处理 部分有序的数据 时特别高效。

  • 稳定性和适应性
    Timsort 是一种稳定的排序算法,能适应不同的数据分布,从完全随机到完全有序的数据都能高效处理。

4.2 Timsort 在不同数据分布下的性能表现如何?

(1)完全随机的数据
  • Timsort 的性能接近归并排序,时间复杂度为 O(nlogn)
  • 因为数据完全随机,没有太多的自然有序序列,因此主要依赖于插入排序和归并排序的组合。
(2)部分有序的数据
  • 性能优势明显。可利用已存在的有序序列(run),减少归并的次数和复杂度。
  • 时间复杂度接近 O(n),在某些情况下甚至可以达到线性时间复杂度。
(3)已经排序的数据
  • Timsort 的性能最佳。由于整个数组已经有序,Timsort 可以直接将整个数组视为一个有序序列,时间复杂度为 O(n)。这是 Timsort 的显著优势,因为它能够高效处理已经部分排序的数据。

4.3 如何根据实际需求调整 Timsort 的参数以优化性能?

只提供了优化建议方向,还需要在实际项目中具体实践。

(1)大规模数据排序

较大的 min_run 值可以减少归并的次数,但会增加插入排序的开销。可通过实验和性能测试来选择最优的 min_run 值。通常,min_run 在 32 ~ 64 间是一个较好的选择。

(2)性能敏感的排序任务

可以对 Timsort 进行微调,如

  • 优化插入排序的实现,减少不必要的操作。
  • 使用更高效的归并操作,减少内存开销
  • 根据数据的特性调整 min_run 的值

4.4 改进方向

  • 可以利用多核处理器的优势,将 Timsort 的归并阶段并行化(在归并多个有序块时,可以将每个归并任务分配给不同的线程),使其支持多线程或并行排序。
  • 归并操作中,可以使用原地归并(in-place merge)算法,如用三指针原地归并,减少额外的内存开销。
  • 也可以适用于链表排序。由于链表的随机访问效率较低,可对归并操作进行优化,减少随机访问的次数。
  • 对无法全部加载到内存的大规模数据,可与外部排序算法结合,如:将数据分块加载到内存中,用 Timsort 对每个块排序,然后将排序后的块写入磁盘,最后进行多路归并。
  • 也可以结合快速排序的分区思想,对 Timsort 进行优化。如在归并阶段,可用快排的分区算法来减少归并次数。

相关文章:

Timsort 算法

文章目录 1 基础理解1.1 定义和原理1.2 工作原理 2 算法实现2.1 Python 代码实现2.1.1 代码2.1.2 核心逻辑计算最小运行长度&#xff08;calc_min_run(n)&#xff09;插入排序&#xff08;insertion_sort(arr, left, right)&#xff09; 2.2 Java 代码实现2.3 C 代码实现 3 逻辑…...

Go构建高并发权重抽奖系统:从设计到优化全流程指南

引言&#xff1a;为何需要专业抽奖系统&#xff1f; 在现代互联网应用中&#xff0c;抽奖系统被广泛用于营销活动、用户激励等场景。一个好的抽奖系统需要满足&#xff1a; 公平性&#xff1a;确保概率分布准确高性能&#xff1a;支持高并发抽奖请求安全性&#xff1a;防止作…...

深度学习计算

深度学习的飞速发展离不开强大的计算能力支撑。从张量计算到 GPU 加速&#xff0c;从自动微分到分布式计算&#xff0c;深度学习计算的每一项技术都如同精密仪器中的关键齿轮&#xff0c;推动着模型性能的不断提升。本文深入剖析深度学习计算的核心技术、优化策略以及前沿趋势&…...

【Bluedroid】蓝牙 HID DEVICE 初始化流程源码解析

本文深入剖析Android蓝牙协议栈中HID设备&#xff08;BT-HD&#xff09;服务的初始化与启用流程&#xff0c;从接口初始化、服务掩码管理、服务请求路由到属性回调通知&#xff0c;完整展现蓝牙HID服务激活的技术路径。通过代码逻辑梳理&#xff0c;揭示服务启用的核心机制&…...

Kotlin 中的 Unit 类型的作用以及 Java 中 Void 的区别

在 Kotlin 中&#xff0c;Unit 类型和 Java 中的 void 关键字都用于表示“没有返回值”的函数&#xff0c;但它们在设计理念、类型系统和实际使用中有显著的区别。 1 Kotlin 中的 Unit 类型 表示无返回值&#xff1a; 当函数不返回有意义的值时&#xff0c;Kotlin 使用 Unit …...

Gemini 2.5 推动视频理解进入新时代

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…...

Spark Streaming 内部运行机制详解

核心思想&#xff1a;将实时数据流切割为“微批次”&#xff0c;利用 Spark Core 的批处理能力进行准实时计算。 1. 核心流程拆解 数据接收&#xff08;Input Data Stream&#xff09; 输入源&#xff1a;Kafka、Flume、Socket 等实时数据流。 接收器&#xff08;Receiver&…...

Feign+Resilience4j实现微服务熔断机制:原理与实战

引言&#xff1a;为什么需要熔断器&#xff1f; 在微服务架构中&#xff0c;服务间的依赖调用变得非常普遍。想象一下这样的场景&#xff1a;订单服务依赖支付服务&#xff0c;支付服务又依赖银行网关服务。如果银行网关服务出现故障&#xff0c;故障会向上蔓延&#xff0c;导…...

什么是SparkONYarn模式

1. 什么是 Spark on YARN&#xff1f; Spark on YARN 是 Apache Spark 的一种部署模式&#xff0c;允许 Spark 应用程序在 Hadoop YARN 集群上运行&#xff0c;充分利用 YARN 的资源管理和调度能力。这种模式将 Spark 与 Hadoop 生态深度集成&#xff0c;使企业能够在同一集群…...

鸿蒙北向应用开发: deveco5.0 创建开源鸿蒙项目

本地已经安装deveco5.0 使用5.0创建开源鸿蒙项目 文件->新建->新建项目 直接创建空项目,一路默认 next 直接编译项目 直接连接开源鸿蒙5.0开发板编译会提示 compatibleSdkVersion and releaseType of the app do not match the apiVersion and releaseType on the dev…...

操作系统:内存管理

目录 1、主要目标 2、核心概念和技术 2.1 物理内存与虚拟内存 2.2 内存分页机制 2.3 页面置换算法 3、监控与性能优化 3.1 查看物理内存 3.2 查看虚拟内存 3.3 性能问题 1> 内存不足&#xff08;OOM&#xff09; 2> 内存泄漏 3> 内存碎片 3.4 性能优化策…...

腾讯优化DeepSeek的DeepEP通信框架:开启AI大模型训练新时代

事件背景 在人工智能&#xff08;AI&#xff09;技术迅猛发展的当下&#xff0c;大规模AI模型训练的需求与日俱增。高效的数据通信成为了提升AI模型训练效率的关键环节。混合专家模型&#xff08;MoE&#xff09;作为一种高效的大模型架构&#xff0c;通过动态分配专家网络处理…...

CSP-J普及组第一轮真题单选题专项训练(二)

CSP-J普及组第一轮真题单选题专项训练(二) (共15题,每2分,共30分;每题有且有一个正确选项) 1、一个 32 位整型变量占用()个字节。 A. 32 B. 128 C. 4 D. 8 2、在内存储器中每个存储单元都被赋予一个唯一的序号,称为 A、下标 B、序号 C、地址 D、编号 3、编译器的主要…...

Android加固工具测评:易盾、顶象、360加固哪款更好用?

应用安全已经成为每个开发者和企业关注的核心问题。随着黑客技术的不断升级&#xff0c;单一的安全措施已经无法有效应对各种复杂的攻击威胁。Android加固工具应运而生&#xff0c;成为了提升应用安全的关键利器。这些加固工具通过代码混淆、加密、防篡改等技术手段&#xff0c…...

C++ 字符格式化输出

文章目录 一、简介二、实现代码三、实现效果 一、简介 这里使用std标准库简单实现一个字符格式化输出&#xff0c;方便后续的使用&#xff0c;它有点类似Qt中的QString操作。 二、实现代码 FMTString.hpp #pragma once#include <cmath> #include <cstdio> #include…...

内存中的“BANK”

一、BANK的定义与物理结构 基本概念 BANK&#xff08;存储体&#xff09; 是内存芯片内部的一个逻辑或物理分区&#xff0c;每个BANK由存储单元阵列、地址解码电路和缓冲器组成&#xff0c;用于分块管理内存操作。 作用&#xff1a;通过并行操作减少访问冲突&#xff0c;提升内…...

D-Pointer(Pimpl)设计模式(指向实现的指针)

Qt 的 D-Pointer&#xff08;Pimpl&#xff09;设计模式 1. Pimpl 模式简介 Pimpl&#xff08;Pointer to Implementation&#xff09;是一种设计模式&#xff0c;用于将类的接口与实现分离&#xff0c;从而隐藏实现细节&#xff0c;降低编译依赖&#xff0c;提高代码的可维护…...

XA协议和Tcc

基于 XA 协议的两阶段提交 (2PC)。这是一种分布式事务协议&#xff0c;旨在保证在多个参与者&#xff08;通常是不同的数据库或资源管理器&#xff09;共同参与的事务中&#xff0c;所有参与者要么都提交事务&#xff0c;要么都回滚事务&#xff0c;从而维护数据的一致性。 你…...

我们该如何使用DeepSeek帮我们减负?

在当今信息爆炸的时代&#xff0c;如何快速获取、筛选和分析信息已经成为各行各业的重要能力。而DeepSeek作为一种先进的智能搜索和信息挖掘工具&#xff0c;能够帮助用户快速找到所需的信息&#xff0c;并从海量数据中提取出有用的洞见。在这篇博文中&#xff0c;我们将深入探…...

25.5.13

感觉很久没有写算法题了&#xff0c;先来个滑动队列模板题试试水&#xff0c;就是用双端队列来实现会很方便&#xff0c;拿结构体来记录是第几个数和数的值即可&#xff0c;再定义两个双端队列&#xff0c;一个使他的值单调递增一个使他的值单调递减 使队头元素为最大值或者是最…...

软件测试——面试八股文(入门篇)

今天给大家分享软件测试面试题入门篇&#xff0c;看看大家能答对几题 一、 请你说一说测试用例的边界 参考回答&#xff1a; 边界值分析法就是对输入或输出的边界值进行测试的一种黑盒测试方法。通常边界值分析法是作为对等价类划分法的补充&#xff0c;这种情况下&#xff…...

脑机接口技术:开启人类与机器融合的新时代

摘要 脑机接口&#xff08;BCI&#xff09;技术作为一项前沿科技&#xff0c;正在逐步打破人类与机器之间的沟通障碍&#xff0c;为医疗、娱乐、教育等多个领域带来前所未有的变革。本文将详细介绍脑机接口技术的基本原理、发展现状、应用场景以及面临的挑战和未来发展趋势&…...

当三维地理信息遇上气象预警:电网安全如何实现“先知先觉”?

极端天气频发的当下&#xff0c;一场台风、一次暴雨就可能让电力系统陷入瘫痪。但你知道吗&#xff1f;如今的电网已能通过三维地理信息与气象数据的深度融合&#xff0c;在灾害来临前精准锁定风险&#xff0c;甚至将停电事故减少七成以上。这背后&#xff0c;正是国网电力空间…...

C++ string数据查找、string数据替换、string子串获取

string查找示例见下&#xff0c;代码见下&#xff0c;以及对应运行结果见下&#xff1a; #include<iostream>using namespace std;int main() {// 1string s1 "hellooooworld";cout << s1.find("oooo") << endl;// 2cout << (in…...

2025.5.13山东大学软件学院计算机图形学期末考试回忆版本

2025.5.13山东大学软件学院计图期末考试回忆版本 学院&#xff1a;软件学院 老师&#xff1a;周元峰、魏广顺 一、简述题&#xff08;2024原题一&#xff09; 1.图形绘制流水线的组成和作用 2.双缓冲机制是什么&#xff0c;有什么作用&#xff1f; 3.Delaunay三角化的四条…...

思极地图使用

思极地图api文档&#xff1a;思极地图开放平台 | 思极地图API SDK 思极地图SDK: <script src"https://map.sgcc.com.cn/maps?v3.0.0"></script> <script src"https://map.sgcc.com.cn/products/js-sdk/v3/assets/js/jquery-1.11.1.min.js&quo…...

Fiori学习专题四十一:表单控件

上节课我们学习了一些单一控件的使用&#xff0c;但是我们发现在页面内每个控件都占用了一行&#xff0c;这样子就显得不太好看&#xff0c;这节课我们引入一个表单控件来美化一下这个页面。 1.学习表单控件FORM之前我们先了解下哪些情况会使用到表单控件&#xff0c;最常见的场…...

基于STM32、HAL库的TDA7719TR音频接口芯片驱动程序设计

一、简介: TDA7719TR 是 NXP Semiconductors 推出的高性能音频处理芯片,专为汽车音响系统设计。它集成了 AM/FM 收音机调谐器、音频处理和音量控制功能,支持 I2C 控制接口,非常适合与 STM32 微控制器配合使用。 二、硬件接口: 典型的 STM32L4 与 TDA7719TR 硬件连接如下…...

Baklib智能云平台加速企业数据治理

Baklib数据治理核心优势 Baklib作为新一代企业级知识中台&#xff0c;其数据治理能力建立在全资产统一管理与智能化处理框架的双重基础之上。通过构建知识中台的核心架构&#xff0c;平台实现了图文、音视频等多模态数据的标准化存储与动态标签体系&#xff0c;有效解决传统管…...

面试中被问到谈谈你对threadlocal的理解

ThreadLocal 的核心理解 1. 基本概念 ThreadLocal 是 Java 提供的线程局部变量机制&#xff0c;用于在多线程环境中为每个线程维护独立的变量副本&#xff0c;实现线程隔离。其核心思想是空间换时间&#xff0c;通过避免共享变量带来的同步开销&#xff0c;提升并发性能。 2…...

Spring Boot 应用中实现基本的 SSE 功能

SSE 技术简介 SSE&#xff08;Server-Sent Events&#xff09;是一种允许服务器主动向客户端推送数据的技术。它基于 HTTP 长连接&#xff0c;使用简单&#xff0c;特别适合实时数据更新场景&#xff0c;如股票行情、新闻推送等。与 WebSocket 相比&#xff0c;SSE 更轻量级&a…...

【2025最新】Windows系统装VSCode搭建C/C++开发环境(附带所有安装包)

文章目录 为什么选择VSCode作为C/C开发工具&#xff1f;一、VSCode安装过程&#xff08;超简单&#xff01;&#xff09;二、VSCode中文界面设置&#xff08;再也不用对着英文发愁&#xff01;&#xff09;三、安装C/C插件&#xff08;编程必备神器&#xff01;&#xff09;四、…...

【MyBatis-8】MyBatis对象关联查询详解:高效处理复杂关系映射

在实际业务开发中&#xff0c;我们经常需要处理对象之间的关联关系&#xff0c;如一对一、一对多、多对多等。MyBatis作为一款优秀的持久层框架&#xff0c;提供了强大的对象关联查询能力。本文将深入探讨MyBatis中各种关联查询的实现方式、适用场景及最佳实践。 1. MyBatis关…...

Java基础(IO)

所有操作都在内存&#xff0c;不能长时间保存&#xff0c;IO主要在硬盘&#xff0c;可以长时间保存。 一、File类 File类被定义为文件和目录路径名的抽象表示形式&#xff0c;这是因为 File 类既可以表示文件也可以表示目录&#xff0c;他们都通过对应的路径来描述。 提供构…...

Trae IDE:AI深度集成的智能开发环境

&#xff08;以高效人机协作重塑编程体验&#xff09; 概述 Trae IDE&#xff08;发音 /treɪ/&#xff09;是一款深度集成AI能力的现代化开发工具&#xff0c;结合传统IDE的完备功能与前沿AI技术&#xff0c;提供智能问答、代码自动补全、跨文件编程及AI Agent驱动的自动化开…...

网站开发过程中样式忽然不显示问题

老规矩&#xff0c;先听故事&#xff1a;今天我开发网站时候遇到一个问题&#xff0c;就开发的这个网站在默认127.0.0.1运行样式有bug显示不出来&#xff0c;之前都可以&#xff0c;就完全一样的代码&#xff0c;之前可以正常运行显示&#xff0c;今天忽然就不行了&#xff0c;…...

双种群进化算法:动态约束处理与资源分配解决约束多目标优化问题

双种群进化算法&#xff1a;动态约束处理与资源分配解决约束多目标优化问题 一、引言 约束多目标优化问题&#xff08;CMOPs&#xff09;在工程设计、资源分配等领域广泛存在&#xff0c;其核心是在满足多个约束条件的同时优化多个目标函数。传统方法往往难以平衡约束满足与目…...

如何在 CentOS 7 虚拟机上配置静态 IP 地址并保持重启后 SSH 连接

在使用 CentOS 7 的虚拟机时&#xff0c;我们通常需要配置静态 IP 地址&#xff0c;以确保在每次虚拟机重启后能够通过 SSH 连接。本文将介绍如何在 CentOS 7 系统中配置静态 IP 地址&#xff0c;并确保配置在系统重启后依然生效。 步骤 1&#xff1a;检查虚拟机网络接口 首先…...

整数和浮点数转换时的精度损失

文章目录 int和float转换时的精度损失float组成解析&#xff08;1&#xff09; 32位浮点数的结构&#xff08;2&#xff09;示例&#xff1a;解析一个浮点数&#xff08;3&#xff09;偏置值的作用&#xff08;4&#xff09; 偏置值为什么是127&#xff1f;&#xff08;5&#…...

Protobuf工具

#region 知识点一 什么是 Protobuf //Protobuf 全称是 protocol - buffers&#xff08;协议缓冲区&#xff09; // 是谷歌提供给开发者的一个开源的协议生成工具 // 它的主要工作原理和我们之前做的自定义协议工具类似 // 只不过它更加的完善&…...

闭包原理与常见陷阱

引言 JavaScript闭包是前端开发中既强大又神秘的概念&#xff0c;它不仅是面试的必考题&#xff0c;更是解决复杂问题的利器。闭包让函数能够记住并访问其创建时的作用域&#xff0c;即使在该函数在其定义环境之外执行。 然而&#xff0c;正如许多强大的工具一样&#xff0c;…...

用 VS Code / PyCharm 编写你的第一个 Python 程序

用ChatGPT做软件测试 编写你的第一个 Python 程序——不只是“Hello, World”&#xff0c;而是构建认知、习惯与未来的起点 “第一行代码&#xff0c;是一个开发者认知世界的方式。” 编程的入门&#xff0c;不只是运行一个字符串输出&#xff0c;更是开始用计算机思维来理解、…...

Linux学习心得问题整理(一)

day01 运维初识 理解云计算运维目的是什么&#xff1f; 搭建云计算更有利于我们在公网环境下方便访问我们服务 节省时间的成本&#xff0c;能随时随地方便调度硬件资源&#xff0c;更容易搭建软件服务 安全可靠&#xff0c;售后期间支持技术支持维护 什么是运维&#xff1f…...

在scala中sparkSQL连接masql并添加新数据

以下是 Scala 中使用 Spark SQL 连接 MySQL 并添加数据的完整代码示例&#xff08;纯文本&#xff09;&#xff1a; 1. 准备连接参数&#xff08;需替换实际信息&#xff09; scala val jdbcUrl "jdbc:mysql://localhost:3306/test_db?useUnicodetrue&characterEnc…...

STM32F103_LL库+寄存器学习笔记22 - 基础定时器TIM实现1ms周期回调

导言 如上所示&#xff0c;STM32F103有两个基本定时器TIM6与TIM7&#xff0c;所谓「基本定时器」&#xff0c;即功能最简单的定时器。 项目地址&#xff1a; github: LL库: https://github.com/q164129345/MCU_Develop/tree/main/stm32f103_ll_library22_Basic_Timer寄存器方…...

.Net HttpClient 使用Json数据

HttpClient 使用Json数据 现代Web项目中&#xff0c;Json是最常用的数据格式。不论是前后端的交互中&#xff0c;还是纯前端项目中&#xff0c;都是如此。因此&#xff0c;.Net HttpClient 能不能更加方便、快捷的处理Json格式数据&#xff0c;也就至关重要了&#xff01; 文末…...

AI时代,如何实现人机共舞?

在科技飞速发展的当下&#xff0c;人工智能&#xff08;AI&#xff09;已不再是科幻作品中的遥远想象&#xff0c;而是深入渗透到我们生活与工作的方方面面。从智能手机中的语音助手&#xff0c;到金融领域的风险预测模型&#xff1b;从医疗影像的智能诊断&#xff0c;到工业生…...

flea-cache使用之Redis哨兵模式接入

Redis哨兵模式接入 1. 参考2. 依赖3. 基础接入3.1 定义Flea缓存接口3.2 定义抽象Flea缓存类3.3 定义Redis客户端接口类3.4 定义Redis客户端命令行3.5 定义哨兵模式Redis客户端实现类3.6 定义Redis哨兵连接池3.7 定义Redis哨兵配置文件3.8 定义Redis Flea缓存类3.9 定义抽象Flea…...

【Docker】Docker环境下快速部署Ollama与Open-WebUI:详细指南

Docker环境下快速部署Ollama与Open-WebUI&#xff1a;详细指南 在本篇文章中&#xff0c;我们将深入探讨如何在Docker中高效部署 Ollama 和 Open-WebUI&#xff0c;并解决在实际使用中常见的问题&#xff0c;确保你的模型服务稳定高效地运行。 一、Ollama 和 Open-WebUI 快速部…...

FFmpeg在Android开发中的核心价值是什么?

FFmpeg 在 Android 开发中的核心价值主要体现在其强大的多媒体处理能力和灵活性上&#xff0c;尤其在音视频编解码、流媒体处理及跨平台兼容性方面具有不可替代的作用。以下是具体分析&#xff1a; --- 1. 强大的音视频编解码能力 - 支持广泛格式&#xff1a;FFmpeg 支持几乎所…...