快速排序
-
快速排序
- 将列表中第一个元素设定为基准数字,赋值给mid变量,然后将整个列表中比基准小的数值放在基准的左侧,比基准大的数字放到基准的右侧,然后将基准数字左右两侧的序列在根据此方法进行排放。
- 定义两个指针,low指向最左侧,high指向最右侧
- 然后对最右侧指针进行向左移动,移动规则是:如果指针指向的数值比基准小,则将指针指向的数字移动到基准数字原始位置,否则继续移动指针。
- 如果最右侧指针指向的数值移动到基准位置时,开始移动最左侧指针,将其向右移动,如果该指针指向的数值大于基准则将该数值移动到最右侧指针指向的位置,然后停止移动。
- 如果左右侧指针重复,则将基准放入左右指针重复的位置,则基准左侧是比其小的数值,右侧是比其大的数值
代码:
#1.核心操作,将基数mid放置到序列中间,使得基数左侧都是比它小的,右侧是比它大的 def sort(alist): low = 0 #第一个元素下标 high = len(alist)-1 #最后一个元素下标 mid = alist[low] #基数:初始值为序列中的第一个数值 while low != high: #先偏移high while low < high: if mid < alist[high]: #向左偏移high high = high - 1 else:#将high指向的数值放置到左侧的空位 alist[low] = alist[high] break #向右偏移low while low < high: if mid > alist[low]: low += 1 else: alist[high] = alist[low] break alist[low] = mid #alist[high] = mid return alist
#2.将步骤1的核心操作递归作用到基数的左右两侧的子序列中 #如何区分根据基数拆分出的左右子序列呢?可以根据left和right的指向区分不同的子序列 def sort(alist,left,right):#left和right表示当前sort递归作用到哪一个子序列中 low = left #第一个元素下标 high = right #最后一个元素下标 #结束递归的条件 if low > high: return mid = alist[low] #基数:初始值为序列中的第一个数值 while low != high: #先偏移high while low < high: if mid < alist[high]: #向左偏移high high = high - 1 else:#将high指向的数值放置到左侧的空位 alist[low] = alist[high] break #向右偏移low while low < high: if mid > alist[low]: low += 1 else: alist[high] = alist[low] break alist[low] = mid #alist[high] = mid #上述为核心操作,需要将核心操作递归左右到左右子序列中 sort(alist,left,low-1) #将sort作用到左侧序列中 sort(alist,high+1,right) #将sort作用到右侧序列中 return alist 补充,递归结束条件疑问 当递归后,递归的序列会越来越小,当只剩一个的时候,low = high了,当再次递归时,sort(alist,left,low-1)和sort(alist,high+1,right)调用后,都会满足low > high,所以递归结束
上边的快排效率比下图高,但是下图更好理解
def quicksort(array):
if len(array) < 2:
return array ←------基线条件:为空或只包含一个元素的数组是“有序”的
else:
pivot = array[0] ←------递归条件
less = [i for i in array[1:] if i <= pivot] ←------由所有小于等于基准值的元素组成的子数组
greater = [i for i in array[1:] if i > pivot] ←------由所有大于基准值的元素组成的子数组
return quicksort(less) + [pivot] + quicksort(greater)
print quicksort([10, 5, 2, 3])