通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
代码实现
class QuickSort:def __init__(self, data: list):self.data = datadef sort(self):"""就地进行快速排序,不使用额外的空间"""self.__sort(0, len(self.data) - 1)def __sort(self, l:int, r:int):if l >= r:returnp = self.__partition(l, r)self.__sort(l, p - 1)self.__sort(p + 1, r)def __partition(self, l: int, r: int):# print(self.data,self.data[l])j = l# [l+1,j]< v [j+1,i-1]>v# 选择数组第一个元素后面的元素开始比较for i in range(l + 1, r + 1):if (self.data[i] - self.data[l]) < 0:# 小于参考值 需要把当前遍历的数据放到参考数据的左边j = j + 1self.data[i], self.data[j] = self.data[j], self.data[i]self.data[l], self.data[j] = self.data[j], self.data[l]return jdef sort_by_new_arr(self):"""开辟新空间来存储数据"""self.data = self.__sort_by_new_arr(self.data)def __sort_by_new_arr(self,data:list):if len(data) < 2:return data# 选取基准,随便选哪个都可以,选中间的便于理解# mid = data[len(data) // 2]mid = data[0]# 定义基准值左右两个数列left, right = [], []# 从原始数组中移除基准值data.remove(mid)for item in data:# 大于基准值放右边if item >= mid:right.append(item)else:# 小于基准值放左边left.append(item)# 使用迭代进行比较return self.__sort_by_new_arr(left) + [mid] + self.__sort_by_new_arr(right)
优化方案
数据有序
def __partition(self, l: int, r: int):"""对于完全有序的数据来讲,每次排序之后右边的数组只比上次排序前的数组少了一个元素以此类推递时间复杂度为O(n^2) 递归深度变成O(n)优化方案:在待处理的数据中随机选择分界点"""import random# 随机下标p = random.randint(l, r) # l-r之前的随机值self.data[l],self.data[p] = self.data[p],self.data[l]# print(self.data,self.data[l])j = l# [l+1,j]< v [j+1,i-1]>v# 选择数组第一个元素后面的元素开始比较for i in range(l + 1, r + 1):if (self.data[i] - self.data[l]) < 0:# 小于参考值 需要把当前遍历的数据放到参考数据的左边j = j + 1self.data[i], self.data[j] = self.data[j], self.data[i]self.data[l], self.data[j] = self.data[j], self.data[l]return j
二路快排
def sort_two_ways(self):"""双路快速排序"""self.__sort_two_ways(0, len(self.data) - 1)def __sort_two_ways(self, l, r):if l >= r:returnp = self.__sort_two_ways_partition(l, r)self.__sort_two_ways(l, p - 1)self.__sort_two_ways(p + 1, r)def __sort_two_ways_partition(self, l: int, r: int):import random# 随机下标p = random.randint(l, r) # l-r之前的随机值self.data[l], self.data[p] = self.data[p], self.data[l]# [l+1,i-1] <= v [j+1,r]>=vj = ri = l + 1while (True):while (i <= j and self.data[i] - self.data[l] < 0):i += 1while (j >= i and self.data[j] - self.data[l] > 0):j -= 1if (i >= j):breakself.data[i], self.data[j] = self.data[j], self.data[i]i += 1j -= 1self.data[l], self.data[j] = self.data[j], self.data[l]return j
三路快排
def sort_three_ways(self):"""三路快速排序"""self.__sort_three_ways(0, len(self.data) - 1)def __sort_three_ways(self, l, r):if l >= r:returnimport random# 随机下标# p = random.randint(l, r) # l-r之前的随机值# self.data[l], self.data[p] = self.data[p], self.data[l]# [l+1,i-1] <= v [j+1,r]>=vlt = li = l + 1gt = r + 1while (i < gt):if self.data[i] - self.data[l] < 0:lt += 1self.data[i], self.data[lt] = self.data[lt], self.data[i]i+=1elif self.data[i] - self.data[l] > 0:gt -= 1self.data[i], self.data[gt] = self.data[gt], self.data[i]else:i += 1self.data[l], self.data[lt] = self.data[lt], self.data[l]self.__sort_three_ways(l,lt-1)self.__sort_three_ways(gt,r)
时间复杂度
- 最坏情况下 O(n^2) 概率极低
- 复杂度期望值 O(Nlogn) 层数的期望 O(logn)
