快速排序

快排的基本思想是:通过一趟排序将待排记录分割成独立的两部分,其中一部分记录的关键字均比另一部分记录的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序。通常可选第一个记录为基准来重新排列其余记录,另外它需要一个栈空间来实现递归。

通常用第一个记录作为基准的时候

最好情况:每次基准归位,刚好落在序列的中间,将序列均匀的划分为长度相等或相近的两个子序列。栈空间最大深度为log(n+1),1表示最外层参数进栈

时间复杂度:n·log(n)

空间复杂度:log(n)

最坏情况:初始序列已经有序或基本有序时,每趟排序之后基准落在子序列的一端,则为最坏情况。栈空间最大深度为n

时间复杂度:n^2

空间复杂度:n

数据量大且有序时,使用第一个记录为基准排序会很慢,在leetcode 215题中就体现出来了,因此需要用下面方法对最坏情况进行改进

改善基准的选取

1,随机选基准

随机选择基准可以提升最坏情况下的性能,但是在随机选择时也有最坏情况,即每次都选择了有序序列的一端,最坏时间复杂度也是O(N^2),但整体还是比上述以第一个为基准要好。

2,三者取中(a[0],a[-1],a[len(a)//2])

《严 · 数据结构》上推荐使用三者取中,可大大改善快速排序在最坏情况下的性能。

(3,BFPRT是不是也能优化快排的基准选择,如果用了BFPRT,基准每次都划分在序列中间位置,这样总的快排时间复杂度就是优化前的复杂度n·log(n),就不存在最坏O(N^2)的情况。)

改善快排的递归过程

以基准划分序列时,用两个boolean变量标记两指针向中间移动过程中是否进行过交换,若有哪一部分没有进行交换,则无需对这部分进行递归,进而提升了性能。

代码实现

import random

def partition(nums, left, right, base):
'''基准归位'''
if left == right:
return
temp = nums[base]
nums[base], nums[right] = nums[right], nums[base] # 和尾部节点交换 max_index = left
for i in range(left, right):
if nums[i] < temp:
nums[i], nums[max_index] = nums[max_index], nums[i]
max_index += 1
nums[max_index], nums[right] = nums[right], nums[max_index]
return max_index def quick_sort(nums, left, right):
'''快速排序'''
if left >= right:
return base = random.randint(left, right) # 随机选取基准
base_index = partition(nums, left, right, base) quick_sort(nums, left, base_index-1) # 递归左边
quick_sort(nums, base_index+1, right) # 递归右边 if __name__ == '__main__':
nums = [6, 1, 8, 8, 8, 2, 7, 9, 3, 8, 8, 4, 5, 10]
left, right = 0, len(nums) - 1 quick_sort(nums, left, right)
print(nums)

快速选择

和快排partition过程一致,分治过程只操作有用的一半,另一半不管。

import random

def partition(nums, left, right, base):
'''基准归位'''
if left == right:
return
temp = nums[base]
nums[base], nums[right] = nums[right], nums[base] # 和尾部节点交换 max_index = left
for i in range(left, right):
if nums[i] < temp:
nums[i], nums[max_index] = nums[max_index], nums[i]
max_index += 1
nums[max_index], nums[right] = nums[right], nums[max_index]
return max_index def quick_select(nums, left, right, K):
'''快速选择'''
if left == right: # 分治的序列仅剩一个元素,那么就是它了
return nums[left] base = random.randint(left, right) # 随机选取基准
base_index = partition(nums, left, right, base) if base_index == K:
return nums[base_index]
elif base_index > K:
return quick_select(nums, left, base_index-1, K) # 递归左边
else:
return quick_select(nums, base_index+1, right, K) # 递归右边 if __name__ == '__main__':
nums = [6, 1, 8, 8, 8, 2, 7, 9, 3, 8, 8, 4, 5, 10]
nums = list(set(nums))
print(nums) left, right = 0, len(nums) - 1
K = 2 # 第K大 ans = quick_select(nums, left, right, right-K+1) # 等于N-K+1小,10-2+1=9
print(ans)

对快速排序的分析 Quick Sort的更多相关文章

  1. 复杂度分析 quick sort&merge sort

    空间复杂度看新开了什么数据结构就够了 公式=几个点*每个点执行了多少次 二叉树都是n次 二分法查找:lgn 全部查找:n n:找一个数,但是两边都要找.相当于遍历.类似于rotated sorted ...

  2. 基础排序算法之快速排序(Quick Sort)

    快速排序(Quick Sort)同样是使用了分治法的思想,相比于其他的排序方法,它所用到的空间更少,因为其可以实现原地排序.同时如果随机选取中心枢(pivot),它也是一个随机算法.最重要的是,快速排 ...

  3. 交换排序—快速排序(Quick Sort)原理以及Java实现

    交换排序—快速排序(Quick Sort) 基本思想: 1)选择一个基准元素,通常选择第一个元素或者最后一个元素, 2)通过一趟排序讲待排序的记录分割成独立的两部分,其中一部分记录的元素值均比基准元素 ...

  4. [算法]——快速排序(Quick Sort)

    顾名思义,快速排序(quick sort)速度十分快,时间复杂度为O(nlogn).虽然从此角度讲,也有很多排序算法如归并排序.堆排序甚至希尔排序等,都能达到如此快速,但是快速排序使用更加广泛,以至于 ...

  5. [算法] 快速排序 Quick Sort

    快速排序(Quick Sort)使用分治法策略. 它的基本思想是:选择一个基准数,通过一趟排序将要排序的数据分割成独立的两部分:其中一部分的所有数据都比另外一部分的所有数据都要小.然后,再按此方法对这 ...

  6. 快速排序(Quick Sort)的C语言实现

    快速排序(Quick Sort)的基本思想是通过一趟排序将待排记录分割成独立的两部分,其中一部分记录的关键字均比另一部分记录的关键字小,则可分别对着两部分记录继续进行排序,以达到整个序列有序,具体步骤 ...

  7. 快速排序(Quick Sort)

    快速排序是初学者比较难理解的几个算法之一,这里尽可简单化地讲解,希望能帮到大家. 快速排序基本步骤: 从数列中挑出一个元素,称为"基准"(pivot). 重新排序数列,所有元素比基 ...

  8. 快速排序Quick sort

    快速排序Quick sort 原理,通过一趟扫描将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归 ...

  9. Java中的经典算法之快速排序(Quick Sort)

    Java中的经典算法之快速排序(Quick Sort) 快速排序的思想 基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小, 然后再按此方法对 ...

随机推荐

  1. 廖雪峰Java11多线程编程-2线程同步-1同步代码块

    1.线程安全问题 多个线程同时运行,线程调度由操作系统决定,程序本身无法决定 如果多个线程同时读写共享变量,就可能出现问题 class AddThread extends Thread{ public ...

  2. ALS算法实现用户音乐打分预测

    很多人在决定是否看一部电影之前都会去豆瓣看下评分作为参考,看完电影也会给一个自己的分数.每个人对每个商品或者电影或是音乐都有一个心理的分数,这个分数标明用户是否对这个内容满意.作为内容的提供方,如果可 ...

  3. day67test

    作业 1.按照上方 知识点总结 模块,总结今天所学知识点: 2.有以下广告数据(实际数据命名可以略做调整) ad_data = { tv: [ {img: 'img/tv/001.png', titl ...

  4. zepto.js按需载入模板对象

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/Joyhen/article/details/34412103 Zepto.js 是支持移动WebKi ...

  5. 使用 windows 批处理指令(BAT文件)进行压缩文件(zip)解压操作

    以下指令包括文件删除.复制.zip文件解压操作.使用7z指令指令进行解压操作前,需要确保 windows 的 path 系统环境变量中存在7z的安装路径. 7z的下载地址:https://www.7- ...

  6. 2019-6-23-win10-uwp-未给任务-GenerateAppxPackageRecipe-的必需参数-AppxManifestXml-赋值

    title author date CreateTime categories win10 uwp 未给任务 GenerateAppxPackageRecipe 的必需参数 AppxManifestX ...

  7. 彭亮—Python学习

    1.1 Python简单介绍 1.2 安装Python和配置环境 1.配置Python      1.1 下载Python(直接去官网下载就可以)      1.2 安装Python(点解默认安装即可 ...

  8. workbench使用

    1.你是指默认的mysql目录下data里面的'mysql'这个schema没有在workbench里面看到吧?点击菜单-Edit->Preferences里面的SQL Editor,然后把&q ...

  9. Linux 文本处理三剑客之grep

    文本处理都要使用正则表达式,正则表达式有: 基本正则表达式:grep或者egrep -G 扩展正则表达式:egreo或者grep -E Linux 文本处理三剑客: sed:stream editor ...

  10. Java是如何实现跨平台的

    一.Java是如何实现跨平台的 1.我们编写的Java源码,编译后会生成一种 .class 文件,称为字节码文件 2.Java虚拟机JVM就是负责将字节码文件翻译成特定平台下的机器码然后运行.也就是说 ...