快排序解读

news2024/11/18 12:34:12

排序算法是计算机科学中不可或缺的一部分,它们在各种数据处理场景中发挥着关键作用。在众多排序算法中,快速排序以其高效的性能和简洁的实现成为了许多程序员的首选。今天,我们就来深入剖析快速排序算法,了解其原理、实现方式以及应用。

一、快速排序的原理

快速排序的基本思想是采用分治法(Divide and Conquer)来将一个数组排序。它选择一个元素作为“基准”(pivot),通过一趟排序将待排序的数据分割成独立的两部分,其中一部分的所有数据都比基准小,另一部分的所有数据都比基准大,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
在这里插入图片描述

二、快速排序的实现

快速排序的实现主要包括三个步骤:选择基准、划分数组和递归排序。

  1. 选择基准:通常可以选择数组的第一个元素、最后一个元素或者随机选择一个元素作为基准。
  2. 划分数组:将数组划分为两部分,使得一部分的元素都小于基准,另一部分的元素都大于基准。这通常通过遍历数组并交换元素来实现。
  3. 递归排序:对划分后的两部分数组递归地应用快速排序算法。

下面是一个使用Python实现的快速排序示例:

def quicksort(arr):  
    if len(arr) <= 1:  
        return arr  
    pivot = arr[len(arr) // 2]  
    left = [x for x in arr if x < pivot]  
    middle = [x for x in arr if x == pivot]  
    right = [x for x in arr if x > pivot]  
    return quicksort(left) + middle + quicksort(right)  
  
# 示例  
arr = [3,6,8,10,1,2,1]  
print(quicksort(arr))  # 输出: [1, 1, 2, 3, 6, 8, 10]

在这个实现中,我们选择了数组的中间元素作为基准,并使用列表推导式来创建小于、等于和大于基准的元素的子列表。然后,我们递归地对左右两个子列表进行快速排序,并将结果合并起来。

三、快速排序的性能与优化

快速排序的平均时间复杂度为O(n log n),但在最坏情况下,当输入数组已经有序或逆序时,时间复杂度会退化为O(n^2)。为了避免最坏情况的发生,可以采取一些优化措施,如随机选择基准、使用三数取中等方法来选择更好的基准。

此外,快速排序的空间复杂度为O(log n)(递归调用栈),但在原地排序的版本中,空间复杂度可以优化到O(1)。

1. 随机选择基准
随机选择基准可以减少输入数据已经部分有序时对算法性能的影响。Python中的random.choice函数可以用来从列表中随机选择一个元素作为基准。

import random  
  
def partition(arr, low, high):  
    # 随机选择一个基准  
    pivot_index = random.randint(low, high)  
    arr[pivot_index], arr[high] = arr[high], arr[pivot_index]  # 将基准元素放到末尾  
    pivot = arr[high]  
    i = low - 1  # 指向小于基准的元素的指针  
    for j in range(low, high):  
        if arr[j] <= pivot:  
            i += 1  
            arr[i], arr[j] = arr[j], arr[i]  
    arr[i + 1], arr[high] = arr[high], arr[i + 1]  # 将基准元素放到正确的位置  
    return i + 1  
  
def quicksort(arr, low, high):  
    if low < high:  
        pi = partition(arr, low, high)  
        quicksort(arr, low, pi - 1)  
        quicksort(arr, pi + 1, high)  
  
# 示例  
arr = [3, 6, 8, 10, 1, 2, 1]  
n = len(arr)  
quicksort(arr, 0, n - 1)  
print("Sorted array is:", arr)

2. 使用三数取中法选择基准
三数取中法是从待排序序列的首、尾和中间三个元素中选择一个中值作为基准。这种方法可以尽量避免输入数据已排序或逆序时造成的性能下降。

def median_of_three(arr, low, mid, high):  
    if arr[low] > arr[mid]:  
        arr[low], arr[mid] = arr[mid], arr[low]  
    if arr[mid] > arr[high]:  
        arr[mid], arr[high] = arr[high], arr[mid]  
    if arr[low] > arr[mid]:  
        arr[low], arr[mid] = arr[mid], arr[low]  
    return arr[mid]  
  
def partition(arr, low, high):  
    mid = (low + high) // 2  
    pivot = median_of_three(arr, low, mid, high)  
    arr[mid], arr[high] = arr[high], arr[mid]  # 将基准元素放到末尾  
    i = low - 1  # 指向小于基准的元素的指针  
    for j in range(low, high):  
        if arr[j] <= pivot:  
            i += 1  
            arr[i], arr[j] = arr[j], arr[i]  
    arr[i + 1], arr[high] = arr[high], arr[i + 1]  # 将基准元素放到正确的位置  
    return i + 1  
  
def quicksort(arr, low, high):  
    if low < high:  
        pi = partition(arr, low, high)  
        quicksort(arr, low, pi - 1)  
        quicksort(arr, pi + 1, high)  
  
# 示例  
arr = [3, 6, 8, 10, 1, 2, 1]  
n = len(arr)  
quicksort(arr, 0, n - 1)  
print("Sorted array is:", arr)

在上面的代码中,median_of_three函数用来计算三个元素的中值,并将这个中值作为基准。这个基准随后被放到数组的末尾,然后执行标准的快速排序分区操作。注意,这里的分区操作partition函数也做了相应的调整,以配合新的基准选择方法。

四、快速排序的应用

快速排序因其高效的性能而在许多场景中得到了广泛应用。无论是在数据库管理系统中对大量数据进行排序,还是在算法竞赛中解决排序相关问题,快速排序都是一个不错的选择。同时,它也可以作为其他高级算法(如归并排序、堆排序等)的基础组件。

五、总结

快速排序是一种高效且实用的排序算法,通过分治法的思想将问题分解为更小的子问题来解决。在实现快速排序时,需要注意选择合适的基准和避免最坏情况的发生。通过不断优化和改进,我们可以使快速排序在更多场景下发挥出其强大的性能优势。

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

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

相关文章

【【萌新的Pytorch入门之Python的学习】】

学习记录 - 参考记录来自B站up主 -爆肝杰哥 ① NumPy 包为 Python 加上了关键的数组变量类型&#xff0c;弥补了 Python 的不足&#xff1b; ② Pandas 包在 NumPy 数组的基础上添加了与 Excel 类似的行列标签&#xff1b; ③ Matplotlib 库借鉴 Matlab&#xff0c;帮 Python 具…

mysql 基本查询

学习了mysql函数&#xff0c;接下来学习mysql基本查询。 1&#xff0c;基本查询语句 MySQL从数据表中查询数据的基本语句为SELECT 语句。SELECT语句的基本格式是&#xff1a; SELECT (*I <字段列表>} FROM <表1>,<表2>..[WHERE<表达式> [GROUP BY <…

C++入门(以c为基础)——学习笔记2

1.引用 引用不是新定义一个变量&#xff0c;而是给已存在变量取了一个别名&#xff0c;编译器不会为引用变量开辟内存空 间。在语法层面&#xff0c;我们认为它和它引用的变量共用同一块内存空间。 可以取多个别名&#xff0c;也可以给别名取别名。 b/c/d本质都是别名&#…

QA测试开发工程师面试题满分问答3: python的深拷贝和浅拷贝问题

在 Python 中&#xff0c;深拷贝&#xff08;deep copy&#xff09;和浅拷贝&#xff08;shallow copy&#xff09;是用于创建对象副本的两种不同方式。 浅拷贝是创建一个新的对象&#xff0c;该对象与原始对象的内容相同&#xff08;包括内部嵌套对象的引用&#xff09;&…

SSM框架学习——了解Spring与Eclipse创建Maven项目

了解Spring 什么是Spring Spirng是分层的JavaSE/EE全栈轻量级开源框架&#xff0c;以控制反转IoC和面向切面编程AOP为内核&#xff0c;使用基本的JavaBean来完成EJB的工作。 Spring框架采用分层架构&#xff0c;它的一些列功能被分为若干个模块。 上图中的红色背景模块为本…

提示工程概要

提示工程 1. 两大原则 原则 1&#xff1a;编写清晰具体的说明 使用分隔符 三引号&#xff1a;“”"三个反引号&#xff1a;三个破折号&#xff1a;—尖括号&#xff1a;<>XML标签&#xff1a; 要求结构化输出 HTMLJSONXMLPython字典 检查条件是否满足 检查执行…

C++ 类和对象(初篇)

类的引入 C语言中&#xff0c;结构体中只能定义变量&#xff0c;在C中&#xff0c;结构体内不仅可以定义变量&#xff0c;也可以定义函数。 而为了区分C和C我们将结构体重新命名成class去定义 类的定义 标准格式&#xff1a; class className {// 类体&#xff1a;由成员函…

linux安装和使用Rancher

linux安装和使用Rancher Rancher介绍请看如下博客 arm架构安装Rancher并导入k8s集群解决Error: no objects passed to apply 华为云arm架构安装k8s(kubernetes) linux下安装Rancher Rancher部署监控k8s集群状态等,比Dashboard插件强大 提前安装好K8S 在master上执行#如果…

学习心得1

这时我第一次更学习心得&#xff01;不足的在评论区指教。 首先先来分享一下&#xff0c;刷一维数组题目的方法。 仔细读题&#xff0c;不会做的题目先完成输入输出。不要干等着着急&#xff0c;就跳到下一题。如果使用的时oj&#xff0c;那就没有题解但是使用洛谷、LeetCood…

【热门话题】计算机视觉入门:探索数字世界中的“视觉智能”

&#x1f308;个人主页: 鑫宝Code &#x1f525;热门专栏: 闲话杂谈&#xff5c; 炫酷HTML | JavaScript基础 ​&#x1f4ab;个人格言: "如无必要&#xff0c;勿增实体" 文章目录 计算机视觉入门&#xff1a;探索数字世界中的“视觉智能”摘要正文一、计算机视…

MATLAB——知识点备忘

最近在攻略ADC建模相关方面&#xff0c;由好多零碎的知识点&#xff0c;这里写个备忘录。 Matlab 判断一个数是否为整数 1. isinteger 函数 MATLAB中&#xff0c;可以使用 isinteger 函数来判断一个数是否为整数&#xff0c;例如&#xff1a;要判断x是否为整数可以采用以下代…

链式二叉树经典OJ题目(二)

目录 结构体及头文件&#xff1a; 1.二叉树的前序遍历 题目描述&#xff1a; 思路分析&#xff1a; 源码&#xff1a; 2.二叉树的翻转 题目描述&#xff1a; 思路分析&#xff1a; 源码&#xff1a; 3.另一颗子树 题目描述&#xff1a; 思路分析&#xff1a; 源码&…

蓝桥杯单片机真题实践篇

这里就不完全写思路过程代码什么的&#xff0c;这一篇文章就写我在训练真题中遇到的过程。 &#xff08;呜呜呜&#xff0c;时间不够辣&#xff0c;能做多少算多少吧....&#xff09; 十三届省赛题 问题1&#xff1a;数码管的数字消影不明显 &#xff08;参考&#xff1a;蓝…

Splunk Attack Range:一款针对Splunk安全的模拟测试环境创建工具

关于Splunk Attack Range Splunk Attack Range是一款针对Splunk安全的模拟测试环境创建工具&#xff0c;该工具完全开源&#xff0c;目前由Splunk威胁研究团队负责维护。 该工具能够帮助广大研究人员构建模拟攻击测试所用的本地或云端环境&#xff0c;并将数据转发至Splunk实例…

ARM架构学习笔记1-寄存器

ARM内部寄存器 有R0-R1516个寄存器 R0-R12通用目的寄存器Program status Register&#xff1a;程序状态寄存器 &#xff0c;用来保存某些状态的值保存:m3/m4架构保存在xPSR&#xff0c;coretex-A7架构保存在CPSR中XPSR是程序状态寄存器 MRS命令&#xff1a;表示Move to Regis…

Tuxera NTFS for Mac2023绿色免费版 免费的ntfs for mac 免费读写硬盘U盘工具

Tuxera NTFS 2023 Mac免费版是款适合Mac用户使用的磁盘读写工具。Tuxera NTFS 2023 Mac可以很好的帮助用户在Mac上打开、编辑、复制、移动或删除存储在Windows NTFS格式的USB驱动器上的文件。并且Tuxera NTFS 2023 Mac还可以无阻碍地使用各种文件系统磁盘&#xff0c;还能解决磁…

数据生成 | Matlab实现基于K-means和SVM的GMM高斯混合分布的数据生成

数据生成 | Matlab实现基于K-means和SVM的GMM高斯混合分布的数据生成 目录 数据生成 | Matlab实现基于K-means和SVM的GMM高斯混合分布的数据生成生成效果基本描述模型描述程序设计参考资料 生成效果 基本描述 1.Matlab实现基于K-means和SVM的GMM高斯混合分布的数据生成&#xf…

vivado 向 SVF 目标添加器件

向 SVF 目标添加器件 创建 SVF 目标后 &#xff0c; 可向其中添加器件以定义 SVF JTAG 器件链配置。 SVF JTAG 器件链配置应与目标硬件链相匹配 &#xff0c; 以 确保能正确执行 SVF 文件。 使用 Vivado IDE 单击“ ”按钮以向 SVF 链添加赛灵思器件或非赛灵思器件。…

法向量估计

法向量估计 1. 求解点P法向量的原理2. 法向量估计的证明3. 为什么求点P的法向量&#xff0c;需要使用以P为中心的邻域内的点&#xff1f;4. 法向量估计的应用和思考5. 权重法向量估计 1. 求解点P法向量的原理 已知有一组点 P ( p 1 , p 2 , p 3 , . . . , p n ) , p i ∈ R 3…

糖豆人打开失败或无法运行

一般就是网络不行&#xff0c;选择加速器加速就好了。 eg: (uu加速器) 一般直接点启动游戏就行。 如果提示找不到文件路径&#xff0c;或者说直接弹出steam的登录的话就是配置路径有问题。现在糖豆人已经不再steam平台了&#xff0c;应该是epic才对。 配置方法&#xff1a;…