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

python评估算法性能

一.原理分析

1. 时间复杂度

这是最重要的评估指标之一,它描述了算法的运行时间如何随着输入规模的增加而变化

核心思想:我们并不关心具体的运行时间(比如多少毫秒),而是关心增长的趋势。当输入规模n变得非常大时,常数因子和低阶项的影响会变得微不足道,起主导作用的是最高阶项。

大O表示法:用来描述算法运行时间的上界,即最坏情况下的性能。

常见复杂度(从优到劣):

O(1): 常数时间。无论输入多大,运行时间都不变。
def constant_time(arr):return arr[0] if arr else None  # 无论数组多长,只做一次操作def access_dict(dictionary, key):return dictionary.get(key)      # 字典查找平均O(1)# 示例:数组索引、字典查找、算术运算
O(log n): 对数时间。运行时间随输入规模呈对数增长,效率非常高(如二分查找)。
def binary_search(arr, target):left, right = 0, len(arr) - 1while left <= right:            # 每次循环范围减半mid = (left + right) // 2if arr[mid] == target:return midelif arr[mid] < target:left = mid + 1else:right = mid - 1return -1# 输入规模n,循环次数:log₂n
O(n): 线性时间。运行时间与输入规模成正比。
def linear_search(arr, target):for i, item in enumerate(arr):  # 遍历整个数组if item == target:return ireturn -1def sum_array(arr):total = 0for num in arr:                 # 遍历每个元素total += numreturn total# 输入规模n,操作次数:n
O(n log n): 线性对数时间。许多高效排序算法的复杂度(如归并排序、快速排序的平均情况)。
def merge_sort(arr):if len(arr) <= 1:return arrmid = len(arr) // 2left = merge_sort(arr[:mid])    # O(log n) 层递归right = merge_sort(arr[mid:])return merge(left, right)       # 每层合并 O(n)def merge(left, right):result = []i = j = 0while i < len(left) and j < len(right):if left[i] <= right[j]:result.append(left[i])i += 1else:result.append(right[j])j += 1result.extend(left[i:])result.extend(right[j:])return result# 典型算法:归并排序、快速排序(平均情况)、堆排序
O(n²): 平方时间。常见于简单的双重循环(如冒泡排序)。
def bubble_sort(arr):n = len(arr)for i in range(n):              # n 次循环for j in range(0, n-i-1):   # 平均 n/2 次循环if arr[j] > arr[j+1]:arr[j], arr[j+1] = arr[j+1], arr[j]return arrdef find_pairs(arr):pairs = []for i in range(len(arr)):       # n 次循环for j in range(i+1, len(arr)):  # n-i-1 次循环pairs.append((arr[i], arr[j]))return pairs# 总操作次数:n × (n-1)/2 ≈ n²/2 = O(n²)
O(2^n): 指数时间。通常出现在暴力求解问题中,当n较大时几乎不可用。
def fibonacci_naive(n):if n <= 1:return nreturn fibonacci_naive(n-1) + fibonacci_naive(n-2)  # 两次递归调用# 递归树:每个节点分裂为两个子节点
# 时间复杂度:O(2^n)
O(n!): 阶乘时间。性能最差,通常用于解决旅行商等问题。
def generate_permutations(arr):if len(arr) <= 1:return [arr]permutations = []for i in range(len(arr)):rest = arr[:i] + arr[i+1:]for p in generate_permutations(rest):  # 递归调用 (n-1)! 次permutations.append([arr[i]] + p)return permutations# n个元素的排列数:n!,时间复杂度:O(n!)

2. 空间复杂度

空间复杂度衡量的是算法在运行过程中临时占用的存储空间大小随输入规模增长的变化趋势

简单来说,它回答的问题是:"当我的输入数据量翻倍时,这个算法需要多少额外的内存?"

O(1) - 常数空间

算法所需的额外空间不随输入规模n变化。

def constant_space(n):total = 0           # O(1) - 1个变量for i in range(n):  # i 也是 O(1) - 每次循环复用同一个变量total += ireturn total# 无论n多大,只用了固定数量的变量

O(n) - 线性空间

算法所需的额外空间与输入规模n成正比。

def linear_space(n):result = []              # O(n)for i in range(n):result.append(i)     # 列表长度随n线性增长return resultdef another_linear(n):hash_map = {}           # O(n)for i in range(n):hash_map[i] = i * 2  # 字典大小随n线性增长return hash_map

O(n²) - 平方空间

算法所需的额外空间与输入规模n的平方成正比。

def quadratic_space(n):matrix = []                    # O(n²)for i in range(n):row = []                   # 每行 O(n)for j in range(n):row.append(i * j)      # 总共 n * n = n² 个元素matrix.append(row)return matrix

O(log n) - 对数空间

通常出现在递归算法中。

def recursive_function(n):if n <= 1:return n# 递归深度为 O(log n),调用栈空间也是 O(log n)return recursive_function(n // 2) + recursive_function(n // 2)

二.Python性能评估的实践工具

1. 时间测量工具

timeit 模块 - 首选工具
import timeit# 方法1:使用timeit.timeit()
def test_function():return sum(range(1000))# 重复执行10000次,计算总时间
time_taken = timeit.timeit(test_function, number=10000)
print(f"平均时间: {time_taken/10000:.6f}秒")# 方法2:使用timeit.repeat()
times = timeit.repeat(test_function, number=1000, repeat=5)
print(f"最佳时间: {min(times)/1000:.6f}秒")
print(f"最差时间: {max(times)/1000:.6f}秒")
print(f"平均时间: {sum(times)/len(times)/1000:.6f}秒")

2. 内存分析工具

memory_profiler
from memory_profiler import profile@profile
def memory_intensive_function():# 创建大量数据big_list = [i for i in range(100000)]big_dict = {i: str(i) for i in range(100000)}return big_list, big_dictif __name__ == "__main__":memory_intensive_function()

三、完整的性能评估实践示例

让我们通过一个具体的例子来展示完整的评估流程。

import timeit
import random
from collections import defaultdict
import sysdef linear_search(arr, target):"""线性查找 - O(n)"""for i, item in enumerate(arr):if item == target:return ireturn -1def binary_search(arr, target):"""二分查找 - O(log n)"""low, high = 0, len(arr) - 1while low <= high:mid = (low + high) // 2if arr[mid] == target:return midelif arr[mid] < target:low = mid + 1else:high = mid - 1return -1def performance_comparison():"""完整的性能比较函数"""# 准备测试数据sizes = [100, 1000, 10000, 100000]results = defaultdict(dict)for size in sizes:# 生成有序数据(二分查找需要有序数据)sorted_data = list(range(size))target = random.choice(sorted_data)  # 确保目标存在# 测试线性查找linear_time = timeit.timeit(lambda: linear_search(sorted_data, target),number=1000)# 测试二分查找binary_time = timeit.timeit(lambda: binary_search(sorted_data, target),number=1000)results[size] = {'linear_search': linear_time,'binary_search': binary_time,'ratio': linear_time / binary_time}# 输出结果print("性能比较结果:")print("数据规模\t线性查找\t二分查找\t速度比")print("-" * 50)for size in sizes:result = results[size]print(f"{size}\t\t{result['linear_search']:.6f}\t"f"{result['binary_search']:.6f}\t"f"{result['ratio']:.1f}x")if __name__ == "__main__":performance_comparison()

http://www.dtcms.com/a/438898.html

相关文章:

  • 408之cpp(二叉树的广度优先遍历)
  • 保定市网站销售和设计中国各大网站开发语言
  • 本地常州微信网站建设做网站税率
  • 网页设计 做网站的代码公司网站开发项目管理制度
  • EFlat-LoRA 的严格数学推导
  • 【面板数据】全国分省教育支出水平数据集(2007-2023年)
  • 做网站工商局要不要备案呢wordpress主题多页面
  • 济南网站建设服务公司wordpress 远程插件安装 ftp
  • 济南网站建设公司按需定制保险网站建设的目标
  • 深入剖析:boost::intrusive_ptr 与 std::shared_ptr 的性能边界和实现哲学
  • 聊城制作手机网站公司网站建设需要的条件
  • SQL 子查询与多表 JOIN 用法大全(速查版)
  • Leetcode 239. 滑动窗口最大值 优先队列 / 双向单调队列
  • Nacos 工作原理及流量走向
  • 夏津网站建设茂名企业建站程序
  • OSPF 单区域实验 概念及题目
  • 建立一个门户网站WordPress域名后问号英文
  • 自上而下VS自下而上:设计哲学全解
  • 【开题答辩全过程】以 SpringCloud家乡美旅行交流博客平台为例,包含答辩的问题和答案
  • 2015优先中文公司官网wordpress模板
  • 国外优秀企业网站网络空间的竞争归根结底是
  • 哪些外贸网站可以做soho求网站2021给个网址
  • 2022年网站能用的兰州企业网站制作
  • 网页设计与网站建设实战大全推荐好的网站或网页
  • 查看网站是否做百度推广如果在网上接网站建设项目
  • 如何用源码搭建网站源码网站搭建规划
  • 【办公类-117-01】20250924通义万相视频2.5——三个小人(幼儿作品动态化)
  • PBS, 以太坊的棘刺雕猴
  • 【未来】智能体互联时代的商业模式变化和挑战:从HOM到AOM
  • 域名免费注册网站网站模板凡建站