algorithm-in-python/sort/quickSort.py

136 lines
3.6 KiB
Python
Raw Normal View History

2018-07-08 23:28:29 +08:00
''' mbinary
#########################################################################
# File : quickSort.py
# Author: mbinary
# Mail: zhuheqin1@gmail.com
2019-01-31 12:09:46 +08:00
# Blog: https://mbinary.xyz
2018-07-08 23:28:29 +08:00
# Github: https://github.com/mbinary
# Created Time: 2018-07-06 10:31
# Description:
#########################################################################
'''
2019-05-23 23:51:44 +08:00
2020-04-15 12:28:20 +08:00
from time import time
2018-07-08 16:41:55 +08:00
def quickSort(lst):
'''A optimized version of Hoare partition'''
2019-05-23 23:51:44 +08:00
def partition(a, b):
2018-07-08 16:41:55 +08:00
pivot = lst[a]
2019-05-23 23:51:44 +08:00
while a != b:
while a < b and lst[b] > pivot:
b -= 1
if a < b:
2018-07-08 16:41:55 +08:00
lst[a] = lst[b]
2019-05-23 23:51:44 +08:00
a += 1
while a < b and lst[a] < pivot:
a += 1
if a < b:
2018-07-08 16:41:55 +08:00
lst[b] = lst[a]
2019-05-23 23:51:44 +08:00
b -= 1
2018-07-08 16:41:55 +08:00
lst[a] = pivot
return a
2019-05-23 23:51:44 +08:00
def _sort(a, b):
2020-04-15 12:28:20 +08:00
if a >= b:
return
2019-05-23 23:51:44 +08:00
mid = (a + b) // 2
2018-07-08 16:41:55 +08:00
# 三数取中值置于第一个作为 pivot
2019-05-23 23:51:44 +08:00
if (lst[a] < lst[mid]) ^ (lst[b] < lst[mid]):
lst[a], lst[mid] = lst[mid], lst[a] # lst[mid] 为中值
if (lst[a] < lst[b]) ^ (lst[b] > lst[mid]):
lst[a], lst[b] = lst[b], lst[a] # lst[b] 为中值
i = partition(a, b)
_sort(a, i - 1)
_sort(i + 1, b)
_sort(0, len(lst) - 1)
2018-07-08 16:41:55 +08:00
return lst
2019-05-23 23:51:44 +08:00
2018-07-08 16:41:55 +08:00
def quickSort2(lst):
'''A version of partition from <Introduction of Algorithm>, a little bit slow'''
2019-05-23 23:51:44 +08:00
def partition(a, b):
2018-07-08 16:41:55 +08:00
pivot = lst[b]
2019-05-23 23:51:44 +08:00
j = a - 1
for i in range(a, b):
if lst[i] <= pivot:
j += 1
2020-04-15 12:28:20 +08:00
if i != j:
lst[i], lst[j] = lst[j], lst[i]
2019-05-23 23:51:44 +08:00
lst[j + 1], lst[b] = lst[b], lst[j + 1]
return j + 1
def _sort(a, b):
2020-04-15 12:28:20 +08:00
if a >= b:
return
2019-05-23 23:51:44 +08:00
mid = (a + b) // 2
2018-07-08 16:41:55 +08:00
# 三数取中值置于第一个作为 pivot
2019-05-23 23:51:44 +08:00
if (lst[a] < lst[mid]) ^ (lst[b] < lst[mid]):
lst[b], lst[mid] = lst[mid], lst[b] # lst[mid] 为中值
if (lst[a] > lst[b]) ^ (lst[a] > lst[mid]):
lst[a], lst[b] = lst[b], lst[a] # lst[b] 为中值
i = partition(a, b)
_sort(a, i - 1)
_sort(i + 1, b)
2018-07-08 16:41:55 +08:00
2019-05-23 23:51:44 +08:00
_sort(0, len(lst) - 1)
2018-07-08 16:41:55 +08:00
return lst
2019-05-23 23:51:44 +08:00
2018-07-08 16:41:55 +08:00
def quickSort3(lst):
'''A rear recursive optimization version'''
2019-05-23 23:51:44 +08:00
def partition(a, b):
2018-07-08 16:41:55 +08:00
pivot = lst[b]
2019-05-23 23:51:44 +08:00
j = a - 1
for i in range(a, b):
if lst[i] <= pivot:
j += 1
2020-04-15 12:28:20 +08:00
if i != j:
lst[i], lst[j] = lst[j], lst[i]
2019-05-23 23:51:44 +08:00
lst[j + 1], lst[b] = lst[b], lst[j + 1]
return j + 1
def _sort(a, b):
while a < b:
mid = (a + b) // 2
2018-07-08 16:41:55 +08:00
# 三数取中值置于第一个作为 pivot
2019-05-23 23:51:44 +08:00
if (lst[a] < lst[mid]) ^ (lst[b] < lst[mid]):
lst[b], lst[mid] = lst[mid], lst[b] # lst[mid] 为中值
if (lst[a] > lst[b]) ^ (lst[a] > lst[mid]):
lst[a], lst[b] = lst[b], lst[a] # lst[b] 为中值
i = partition(a, b)
_sort(a, i - 1)
a = i + 1
_sort(0, len(lst) - 1)
2018-07-08 16:41:55 +08:00
return lst
2019-05-23 23:51:44 +08:00
def timer(func, lst, n=100):
2018-07-08 16:41:55 +08:00
t = time()
2019-05-23 23:51:44 +08:00
for i in range(n):
func(lst)
t = time() - t
print('{}: {}s'.format(func.__name__, t))
2018-07-08 16:41:55 +08:00
return t
2019-05-23 23:51:44 +08:00
2018-07-08 16:41:55 +08:00
if __name__ == '__main__':
from random import randint
print('5000 items, repeat 100 times for each')
2019-05-23 23:51:44 +08:00
lst = [randint(0, 100) for i in range(5000)]
timer(quickSort, lst.copy())
timer(quickSort2, lst.copy())
timer(quickSort3, lst.copy())
2018-07-08 16:41:55 +08:00
2019-05-23 23:51:44 +08:00
lst = [randint(0, 100) for i in range(15)]
2018-07-08 16:41:55 +08:00
print(lst)
print(quickSort(lst.copy()))
print(quickSort2(lst.copy()))
print(quickSort3(lst.copy()))