排序算法的下界和如何超越下界——python实现Thomas H.Cormen算法基础中的算法

2023-10-11 21:10

本文主要是介绍排序算法的下界和如何超越下界——python实现Thomas H.Cormen算法基础中的算法,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

    • 一、排序算法分类
    • 二、算法复杂度
    • 三、时间复杂度下界
    • 四、超越下界
      • 1.范例1——严格的约束(排序仅有两个值)
      • 2.范例2——扩展1至每个元素可以取m个连续整数中的一个

一、排序算法分类

  • 比较类排序:通过比较来决定元素间的相对次序,由于其时间复杂度不能突破O(nlogn),因此也称为非线性时间比较类排序。
  • 非比较类排序:不通过比较来决定元素间的相对次序,它可以突破基于比较排序的时间下界,以线性时间运行,因此也称为线性时间非比较类排序。

排序算法分类

二、算法复杂度

算法复杂度
相关概念:

  • 稳定:如果a原本在b的前面,而a=b,排序之后a仍然在b的前面
  • 不稳定:如果a原本在b的前面,而a=b,排序之后a可能会出现在b的后面
  • 时间复杂度:对排序数据的总的操作次数。反映当n发生变化的时候,操作次数呈现什么规律
  • 空间复杂度:算法在计算机中执行时所需要存储空间的度量,是数据规模n的函数

三、时间复杂度下界

观察插入排序、希尔排序、选择排序、堆排序、冒泡排序、快速排序、归并排序的时间复杂度,在没有特殊规则的时候时间复杂度为 O ( n l o g n ) O(nlogn) O(nlogn)就是最优的排序算法了

也就是说通用排序算法的时间复杂度下界就是 O ( n l o g n ) O(nlogn) O(nlogn)

如果限定一些规则,是可以打破这个下界的。

下面说一下尽在O(n)时间内就能实现对数组排序的算法、

四、超越下界

问题:基于什么样的规则才能突破排序的下界呢?

基础思想:我们需要分析一下排序消耗的时间。排序需要遍历,比较,交换。能否省略其中的一些步骤呢?这就是要定义的规则,通过规则减少排序步骤。

1.范例1——严格的约束(排序仅有两个值)

一组待排序的元素仅有1和2,没有其它值,对这组数进行排序。

输入 A 0 , A 1 , A 2 , A 3 . . . . . . A n − 1 A_0,A_1,A_2,A_3......A_{n-1} A0A1,A2,A3......An1,Ai为1或者2

排序步骤

  1. 令k=0
  2. 令i从0到n-1依次取值,如果A[i]=1,k自增1
  3. 令i从0到k-1依次取值,将A[i]赋值为1
  4. 令i从k到n-1依次取值,将A[i]赋值为2

这样我们完成了排序,花费的时间为O(n)
之前我们所说的算法都是通过比较元素对来确定顺序,那种排序叫做比较排序。凡是比较排序,通用下界为O(nlogn)

# 非常简单的实现,每一步都对应于上述四个步骤
A = [1,2,1,1,1,2,1,2,1,2,1]
print('排序前:',A)
n = len(A)
k = 0
for i in range(0,n):if A[i]==1:k+=1for i in range(0,k):A[i] = 1for i in range(k,n):A[i] = 2print('排序后:',A)

结果:

排序前: [1, 2, 1, 1, 1, 2, 1, 2, 1, 2, 1]
排序后: [1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2]

2.范例2——扩展1至每个元素可以取m个连续整数中的一个

只要每个元素在m个连续整数值中取值,算法都是通用的

该算法的实现需要三个基本方法:

COUNT-KEY-EQUAL(A,n,m)

输入:A 一个数组,n 数组A中的元素个数m数组A中元素的取值范围
输出:一个数组 e q u a l [ 0...... m ] equal[0......m] equal[0......m],是 e q u a l [ j ] equal[j] equal[j]等于数组A中元素值为j的元素个数

  1. 创建一个新数组 e q u a l [ 0...... m ] equal[0......m] equal[0......m]
  2. e q u a l equal equal数组每个元素都为0
  3. i从0到n-1依次取值,每次将 e q u a l [ A [ i ] ] equal[A[i]] equal[A[i]]的值自增1
  4. 返回 e q u a l equal equal

COUNT-KEY-LESS(equal,m)

输入值COUNT-KEY-EQUAL方法对应的值 e q u a l , m equal,m equalm
输出一个数组 l e s s [ 0...... m ] , l e s s [ j ] = e q u a l [ 0 ] + e q u a l [ 1 ] + . . . . . . + e q u a l [ j − 1 ] less[0......m],less[j]=equal[0]+equal[1]+......+equal[j-1] less[0......m],less[j]=equal[0]+equal[1]+......+equal[j1]

  1. 创建一个新数组 l e s s [ 0... m ] less[0...m] less[0...m]
  2. l e s s [ 0 ] = 0 less[0]=0 less[0]=0
  3. j从1取到m, l e s s [ j ] = l e s s [ j − 1 ] + e q u a l [ j − 1 ] less[j]=less[j-1]+equal[j-1] less[j]=less[j1]+equal[j1](这是普通的迭代算法)
  4. 返回 l e s s less less

REARRANGE(A,less,n,m)

输入COUNT-KEY-EQUAL COUNT-KEY-LESS方法对应的 A , l e s s , n , m A,less,n,m Aless,n,m
输出数组B,B中包含A中所有元素,并且已经排好序

  1. 创建新数组 B [ 0... n − 1 ] , n e x t [ 0..... m ] B[0...n-1],next[0.....m] B[0...n1],next[0.....m]
  2. j从0到m依次取值
    n e x t [ j ] = l e s s [ j ] + 1 next[j]=less[j]+1 next[j]=less[j]+1
  3. 令i从0到n-1依次取值
    k e y = A [ i ] ; i n d e x = n e x t [ k e y ] , B [ i n d e x ] = A [ i ] , n e x t [ k e y ] + + key=A[i];index=next[key],B[index]=A[i],next[key]++ key=A[i];index=next[key],B[index]=A[i],next[key]++
  4. 返回数组B
## 代码实现:
import numpy as np
def CountKeyEqual(A,n,m):equal = np.zeros(m+1)for i in range(0,n):equal[A[i]]+=1return equal
def CountKeyLess(equal,m):less = np.ones(m+1)less[0] = 0 for j in range(1,m+1):less[j] = less[j-1]+equal[j-1]return less
def Rearrange(A,less,n,m):B = np.ones(n)next_ = np.ones(m+1)for j in range(m+1):next_[j] = less[j]+1for i in range(n):key = A[i]index = next_[key]B[int(index)-1] = A[i] # 注意这里与文本序数有些把不同在于B的索引大小应该与A的一致next_[key]+=1return B
if __name__=='__main__':A = [4,1,5,0,1,6,5,1,5,3]n = len(A)m = 6print('排序前:',A)equal = CountKeyEqual(A,n,m)less = CountKeyLess(equal,m)B = Rearrange(A,less,n,m)B = B.astype(np.int).tolist()print('排序后:',B)

结果:

排序前: [4, 1, 5, 0, 1, 6, 5, 1, 5, 3]
排序后: [0, 1, 1, 1, 3, 4, 5, 5, 5, 6]

这篇关于排序算法的下界和如何超越下界——python实现Thomas H.Cormen算法基础中的算法的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/190839

相关文章

基于 HTML5 Canvas 实现图片旋转与下载功能(完整代码展示)

《基于HTML5Canvas实现图片旋转与下载功能(完整代码展示)》本文将深入剖析一段基于HTML5Canvas的代码,该代码实现了图片的旋转(90度和180度)以及旋转后图片的下载... 目录一、引言二、html 结构分析三、css 样式分析四、JavaScript 功能实现一、引言在 Web 开发中,

SpringBoot中使用Flux实现流式返回的方法小结

《SpringBoot中使用Flux实现流式返回的方法小结》文章介绍流式返回(StreamingResponse)在SpringBoot中通过Flux实现,优势包括提升用户体验、降低内存消耗、支持长连... 目录背景流式返回的核心概念与优势1. 提升用户体验2. 降低内存消耗3. 支持长连接与实时通信在Sp

Conda虚拟环境的复制和迁移的四种方法实现

《Conda虚拟环境的复制和迁移的四种方法实现》本文主要介绍了Conda虚拟环境的复制和迁移的四种方法实现,包括requirements.txt,environment.yml,conda-pack,... 目录在本机复制Conda虚拟环境相同操作系统之间复制环境方法一:requirements.txt方法

Spring Boot 实现 IP 限流的原理、实践与利弊解析

《SpringBoot实现IP限流的原理、实践与利弊解析》在SpringBoot中实现IP限流是一种简单而有效的方式来保障系统的稳定性和可用性,本文给大家介绍SpringBoot实现IP限... 目录一、引言二、IP 限流原理2.1 令牌桶算法2.2 漏桶算法三、使用场景3.1 防止恶意攻击3.2 控制资源

基于Python开发Windows屏幕控制工具

《基于Python开发Windows屏幕控制工具》在数字化办公时代,屏幕管理已成为提升工作效率和保护眼睛健康的重要环节,本文将分享一个基于Python和PySide6开发的Windows屏幕控制工具,... 目录概述功能亮点界面展示实现步骤详解1. 环境准备2. 亮度控制模块3. 息屏功能实现4. 息屏时间

Python如何去除图片干扰代码示例

《Python如何去除图片干扰代码示例》图片降噪是一个广泛应用于图像处理的技术,可以提高图像质量和相关应用的效果,:本文主要介绍Python如何去除图片干扰的相关资料,文中通过代码介绍的非常详细,... 目录一、噪声去除1. 高斯噪声(像素值正态分布扰动)2. 椒盐噪声(随机黑白像素点)3. 复杂噪声(如伪

springboot下载接口限速功能实现

《springboot下载接口限速功能实现》通过Redis统计并发数动态调整每个用户带宽,核心逻辑为每秒读取并发送限定数据量,防止单用户占用过多资源,确保整体下载均衡且高效,本文给大家介绍spring... 目录 一、整体目标 二、涉及的主要类/方法✅ 三、核心流程图解(简化) 四、关键代码详解1️⃣ 设置

Python中图片与PDF识别文本(OCR)的全面指南

《Python中图片与PDF识别文本(OCR)的全面指南》在数据爆炸时代,80%的企业数据以非结构化形式存在,其中PDF和图像是最主要的载体,本文将深入探索Python中OCR技术如何将这些数字纸张转... 目录一、OCR技术核心原理二、python图像识别四大工具库1. Pytesseract - 经典O

基于Linux的ffmpeg python的关键帧抽取

《基于Linux的ffmpegpython的关键帧抽取》本文主要介绍了基于Linux的ffmpegpython的关键帧抽取,实现以按帧或时间间隔抽取关键帧,文中通过示例代码介绍的非常详细,对大家的学... 目录1.FFmpeg的环境配置1) 创建一个虚拟环境envjavascript2) ffmpeg-py

Nginx 配置跨域的实现及常见问题解决

《Nginx配置跨域的实现及常见问题解决》本文主要介绍了Nginx配置跨域的实现及常见问题解决,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来... 目录1. 跨域1.1 同源策略1.2 跨域资源共享(CORS)2. Nginx 配置跨域的场景2.1