当前位置:网站首页>递归:快速排序,归并排序和堆排序
递归:快速排序,归并排序和堆排序
2022-07-03 03:28:00 【我家大宝最可爱】
快速排序
快速排序的思想非常的简单,随便找一个元素作为标兵,然后使用双指针分别从左右开始移动,
- 首先让右指针指向数组末尾
R=len(arr)-1
,然后判断是否大等于标兵元素,如果大于的话那么右指针就继续向左侧移动,即R -=1
,直到找到小于标兵的位置 - 然后让左指针指向数组的开始,然后判断是否小于等于标兵元素,如果小于那么指针就持续向右移动,即
L += 1
,直到找到打羽标兵的位置 - 最后交换两个元素,将大的元素放到右侧,小的元素放到左侧。左右指针持续进行,直到两个指针相遇
可以看到快速排序其实就是不断进行交换的操作,操作完一轮之后,再对左右两侧的数据进行同样的操作,把一个大的问题转换成小的问题,所以快排用的就是递归算法。
快排有两个点非常容易写错
与标兵比对的时候包含了等号。这是因为数组中可能有很多数据是与标兵相同的,与标兵相同的元素其实放在左边和放在右边都是可以的,反正最后排序之后都会与标兵相邻。而且还可以避免陷入死循环。例如下面这个数组,如果不加等号的话,你会发现l和r都不会变动。
最外层的循环比较好理解,要求
i<j
,如果l==r
就直接返回即可,不需要排序,但是内层循环中依然有一个i<j
,这是为什么呢?主要是为了防止数组越界当i与j相等的时候,这一轮交换就结束了,然后将这个元素与标兵元素进行互换,标兵元素就到了他该到的位置。
从二叉树的角度更容易理解快速排序,首先就是找到根节点,然后根据根节点将数据分成两部分,左边都是小于等于根节点的,右边都是大于等于根节点的。然后不断向下递归即可。
这里有个优化,就是使用随机选取pivot,这样在原本就是递增的数组中也可以有很好的性能。如果原本就是一个排序好的arr,那么此时就会退化成 O ( n 2 ) O(n^2) O(n2)。
def quickSort(arr, l, r):
if l >= r: # 递归结束
return
pivot_idx = random.randint(l, r) # 随机选择pivot
arr[l], arr[pivot_idx] = arr[pivot_idx], arr[l] # pivot放置到最左边
pivot = arr[l] # 选取最左边为pivot
i, j = l, r # 双指针
while i < j:
while i<j and arr[j] >= pivot: # 找到右边第一个<pivot的元素
j -= 1
while i<j and arr[i] <= pivot: # 找到左边第一个>pivot的元素
i += 1
arr[i],arr[j] = arr[j],arr[i] # 并将其移动到right处
arr[l],arr[i] = arr[i],pivot
quickSort(arr, l, i-1) # 递归对mid两侧元素进行排序
quickSort(arr, i+1, r)
quickSort(arr, 0, len(arr)-1) # 调用快排函数对nums进行排序
return nums
归并排序
归并排序的底层也是递归的思考,其实根快速排序非常的相似。归并排序有两个点
- 我们把数组分成两个,左边和右边。如果左边我们排好序,然后右边也排好序,那么此时只需要将这两个子数组合并成一个即可。那么左右两个数组该如何排序呢?我们先看左边的数组,我们把左边的数组也分成两部分,如果这两部分是排好序的,我们直接合并即可。此时可以看到,我们把大的排序问题,转化成了每一个字部分的排序问题加合并问题。
这个过程用递归写非常的简单
class Solution:
def sortArray(self, nums: List[int]) -> List[int]:
def mergesort(arr, l, r):
if l >= r:
return
m = (l + r) // 2
mergesort(arr,l,m) # 左半部分排序
mergesort(arr,m+1,r) # 右半部分排序
# 排好顺序的左右两部分再进行合并
# 左边数组的范围是l~m
# 右边数组的范围是m+1~r
# 现在就是把这两个有序数组进行合并
i,j = l,m+1
tmp = []
while i <= m and j <= r:
if arr[i] < arr[j]:
tmp.append(arr[i])
i += 1
else:
tmp.append(arr[j])
j += 1
tmp += arr[i:m+1]
tmp += arr[j:r+1]
for k in range(l,r+1):
arr[k] = tmp[k-l]
mergesort(nums, 0, len(nums)-1) # 调用快排函数对nums进行排序
return nums
边栏推荐
- 用Three.js做一個簡單的3D場景
- [MySQL] the difference between left join, right join and join
- [leetcode question brushing day 34] 540 Unique element in array, 384 Disrupt array, 202 Happy number, 149 Maximum number of points on a line
- Vs 2019 installation and configuration opencv
- LVGL使用心得
- Elsevier latex submitted the article pdftex def Error: File `thumbnails/cas-email. jpeg‘ not found: using draf
- Ansible简介【暂未完成(半成品)】
- Ansible introduction [unfinished (semi-finished products)]
- Node start server
- 渤、黄海的潮汐特征
猜你喜欢
【PyG】理解MessagePassing过程,GCN demo详解
FileZilla Client下載安裝
ffmpeg下载安装教程及介绍
Nasvit: neural architecture search of efficient visual converter with gradient conflict perception hypernetwork training
User value is the last word in the competition of mobile phone market
el-tree搜索方法使用
Download and install node, NPM and yarn
Summary of electromagnetic spectrum
Bid farewell to artificial mental retardation: Mengzi open source project team received RMB 100 million financing to help NLP develop
Introduction to mongodb
随机推荐
Use of El tree search method
Mongodb master profile
Pytoch configuration
[MySQL] the difference between left join, right join and join
Spark on yarn资源优化思路笔记
MySQL Real combat 45 [SQL query and Update Execution Process]
900w+ data, from 17s to 300ms, how to operate
Introduction to mongodb
机械臂速成小指南(八):运动学建模(标准DH法)
Lvgl usage experience
解决高並發下System.currentTimeMillis卡頓
Stop using system Currenttimemillis() takes too long to count. It's too low. Stopwatch is easy to use!
基于QT的tensorRT加速的yolov5
Hi3536C V100R001C02SPC040 交叉编译器安装
VS 2019 配置tensorRT生成engine
Learning notes of C programming [compiled by Mr. Tan Haoqiang] (Chapter III sequence programming) 04 C sentence
FileZilla Client下载安装
Vs Code configure virtual environment
Hi3536c v100r001c02spc040 cross compiler installation
How to make backgroundworker return an object