数据结构与算法(11): 一网打尽partition算法及其拓展
Partition(划分)算法在快速排序、TopK问题、三色排序等问题上都能展现其巨大价值,本次文章讲述的是parition算法在这些算法问题上的应用以及partition算法是如何实现的,文章包括以下6个算法的实现:
- 1.partition算法的单指针实现;
- 2.partition算法的双指针实现;
- 3.快速排序 基于双指针partition的实现
- 4.寻找第K个最小的数
- 5.寻找前K个最小的数
- 6.荷兰三色旗问题
算法的IO解释:
- 1.输入一个数组A,把数组A按枢轴(pivot)划分为两部分,左边小于等于枢轴,右边大于等于枢轴,枢轴在两者中间,但是左右两边不排序,并且返回枢轴的位置(下标).
例如:[1,2,6,3,4,5] pivot =4 得到 [2,1,3,4,6,5] 下标:3 - 2.与1一样,不过采用双指针扫描,时间复杂度更低。
- 3.基于2实现快速排序
- 4.输入一个数组,输出第K个最小的数,并对数组排序了(A[k-1]为第K个最小的数)
- 5.输入一个数组,输出前K个最小的数,并对数组排序了(同上)
- 6.输入一个数组,输出分界点pos_small和pos_big,pos_small左边全是小于target的值,pos_big右边全是大于target的值,两者之间的值等于target,并且数组被排序了。荷兰问题是6的子集中,即输入的数组值只有三种情况,代码完全不变。
算法的实现如下,解释见注释
# -*- coding: utf-8 -*-
# @time : 2019/5/3 22:21
# @Author: LSayhi
# @github: https://github.com/LSayhi
"""1.一个指针实现划分函数"""
def partition_OnePoint(array,begin,end):
pivot = array[begin]#枢轴,可以取数组中任意一个位置的值,这里取第一个,方便说明
pos = begin #记录分界点(其左边<=pivot,其右边>pivot)
for i in range(begin+1,end):#从左到右遍历数组
if array[i] <= pivot:#如果i处的值小于枢轴,则把pos向后移移一位
pos += 1
if pos != i:# 如果pos<i了(说明pos位置的值大于pivot),则把pos的值与i处的交换
temp = array[i]
array[i] = array[pos]
array[pos] = temp
array[begin] = array[pos]
array[pos] = pivot #最后两行是交换pos处与pivot(begin处的值),把pivot放入中间,左边全部<=pivot,右边全部>pivot
return pos
"""2.两个指针实现划分函数"""
def partition_TwoPoint(array,begin,end):
pivot = array[begin]#枢轴
while begin < end:#两个指针begin、end
while(begin < end and array[end] >= pivot):#end从右向左
end -= 1 # 一直向左移,其它不动
array[begin] = array[end] #当array[end]<= pivot,将其赋值给begin位置(即小的放左边去)
while(begin < end and array[begin]<= pivot):
begin += 1 #一直向右移
array[end]