1.快速排序
時間複雜度 :最好O(nlogn)
,最壞O(n^2)
空間複雜度 :O(1)
Partition主要思想是:將小於v和大於v的部分都放到索引值i的左邊
def _partition(nums,l,r):
'''
將數組第一個數視爲base,目的是將所有小數放到左邊,大數放到右邊,返回正確分割的索引
'''
base = nums[l] #即圖片的v
j = l+1
for i in range(l+1, r+1):
if nums[i] < base: #遍歷數組剩下的數,如果小於base則依次放在base的後面
nums[i], nums[j] = nums[j], nums[i]
j += 1
print(nums)
nums[l], nums[j-1] = nums[j-1], nums[l] #把base值放到正確的位置
print(nums)
return j-1
def _quick_sort(nums,l,r):
if l < r:
m = _partition(nums,l,r)
_quick_sort(nums,l,m-1)
_quick_sort(nums,m+1,r)
def quick_sort(nums):
l, r = 0, len(nums)-1
_quick_sort(nums,l,r)
當待排序數組是一個近乎有序
的序列時,容易產生最壞O(n^2)的時間複雜度。
改進辦法:base隨機選取
def _partition_random(nums,l,r):
ind = random.randint(l,r)
nums[l], nums[ind] = nums[ind], [l]
##### 後面的內容同_partition,故省略 #####
2.雙路快排
當待排序數組是一個數值重複率非常高
的序列時,容易產生最壞O(n^2)的時間複雜度。
產生下圖所示的情況,左右子樹不均衡:
Partition主要思想是:將小於v的部分放到指針i(i爲遍歷用指針)的左邊,將大於v的部分都放到指針j的右邊,延用隨機選base的思路。等於v時使用交換的方式處理。
import random
def _partition_doubule(nums, l, r):
ind = random.randint(l, r)
nums[l], nums[ind] = nums[ind], nums[l]
base = nums[l]
i, j = l+1, r
while True:
while i <= r and nums[i] < base: # 不能改爲nums[i] <= base, 因爲這種方式則 # 會將連續出現的這些值歸爲其中一方,使得兩棵子樹不平衡
i += 1
while j >= l + 1 and nums[j] > base: # 不能改爲nums[j] >= base.
j -= 1
if i > j:
break
else:
nums[i], nums[j] = nums[j], nums[i]
i += 1
j -= 1
nums[j], nums[l] = nums[l], nums[j]
return j
def _quick_sort(nums, l, r):
if l < r :
m = _partition_doubule(nums, l, r)
_quick_sort(nums, l, m - 1)
_quick_sort(nums, m + 1, r)
def quick_sort(nums):
l, r = 0, len(nums)-1
_quick_sort(nums,l,r)
3.三路快排
Partition主要思想是:將小於v的部分放到指針lt左邊,將大於v的部分放到指針gt右邊。考慮到v有重複值的情況,遇到等於v的情況,將i指針右移。
import random
def _partition(nums, l, r):
ind = random.randint(l, r)
nums[l], nums[ind] = nums[ind], nums[l]
base = nums[l]
lt = l # nums[l+1...lt] < base
gt = r + 1 # nums[gt...r] > base
i = l + 1 # nums[lt+1...i] == base
while (i < gt):
# i==gt時表示已經比較結束
if (nums[i] < base):
nums[i], nums[lt+1] = nums[lt+1], nums[i]
lt += 1
i += 1
elif (nums[i] > base):
nums[i], nums[gt-1] = nums[gt-1], nums[i]
gt -= 1
else: # nums[i] == base
i += 1
print(nums)
nums[l], nums[lt] = nums[lt], nums[l]
print(nums)
return lt, gt
def _quick_sort(nums, l, r):
if l < r:
lt, gt = _partition(nums, l, r)
_quick_sort(nums, l, lt - 1)
_quick_sort(nums, gt, r)
def quick_sort(nums):
l, r = 0, len(nums) - 1
_quick_sort(nums, l, r)
引用:
1.快速排序時間複雜度爲O(n×log(n))的證明
2.排序算法—快速排序,隨機快速排序和雙路快排(python版)
3.歸併排序、快速排序、二路快排、三路快排python實現
4.十大經典排序算法(動圖演示)