一、前言
1.1、基本思想
快速排序使用分治的思想,通过一趟排序将待排序列分割成两部分,其中一部分记录的关键字均比另一部分记录的关键字小。之后分别对这两部分记录继续进行排序,以达到整个序列有序的目的。
1.2、算法步骤
- 选择基准:在待排序列中,按照某种方式挑出一个元素,作为 “基准”(pivot);
- 分割操作:以该基准在序列中的实际位置,把序列分成两个子序列。此时,在基准左边的元素都比该基准小,在基准右边的元素都比基准大;
- 递归操作:递归地对两个序列进行快速排序,直到序列为空或者只有一个元素。
1.3、选择基准的方式
对于分治算法,当每次划分时,算法若都能分成两个等长的子序列时,那么分治算法效率会达到最大。也就是说,基准的选择是很重要的。选择基准的方式决定了两个分割后两个子序列的长度,进而对整个算法的效率产生决定性影响。
最理想的方法是,选择的基准恰好能把待排序序列分成两个等长的子序列,
下面介绍三种实现方式:
- 分割交换排序:取序列的第一个或最后一个元素作为基准;
- 随机排序:取待排序列中任意一个元素作为基准;
- 中位数排序:对待排序序列中low、mid、high三个位置上数据进行排序,取他们中间的那个数据作为枢轴,并用0下标元素存储枢轴。
二、算法实现
2.1.分割交换排序
代码
import random
import datetime
def random_int_list(start, stop, length):
start, stop = (int(start), int(stop)) if start <= stop else (int(stop), int(start))
length = int(abs(length)) if length else 0
random_list = []
for i in range(length):
random_list.append(random.randint(start, stop))
return random_list
def partition(li, left, right):
"""
归位函数
"""
tmp = li[left]
while left < right:
while left < right and li[right] >= tmp:
right -= 1
li[left] = li[right]
while left < right and li[left] <= tmp:
left += 1
li[right] = li[left]
li[left] = tmp
return left
def quick_sort(li, left, right):
if left < right:
mid = partition(li, left, right)
quick_sort(li, left, mid - 1)
quick_sort(li, mid + 1, right)
def sort(li):
return quick_sort(li, 0, len(li) - 1)
if __name__ == '__main__':
li=random_int_list(1,100000,100)
print("initial array:\n",li)
oldtime=datetime.datetime.now()
sort(li)
newtime=datetime.datetime.now()
print("result array:\n",li)
print(u'运算时间为:%s微秒'%(newtime-oldtime).microseconds)
测试数据
测试数据量 | 时间 |
---|
100 | 116微秒 |
500 | 731微秒 |
1000 | 1623微秒 |
2000 | 3760微秒 |
3000 | 5928微秒 |
4000 | 8203微秒 |
5000 | 10299微秒 |
100000 | 345600微秒 |
200000 | 704385微秒 |
2.2.随机排序
代码
import random
import datetime
def random_int_list(start, stop, length):
start, stop = (int(start), int(stop)) if start <= stop else (int(stop), int(start))
length = int(abs(length)) if length else 0
random_list = []
for i in range(length):
random_list.append(random.randint(start, stop))
return random_list
def quicksort(arr,firstIndex, lastIndex):
if firstIndex<lastIndex:
divIndex=random_partition(arr,firstIndex, lastIndex)
quicksort(arr,firstIndex,divIndex)
quicksort(arr,divIndex+1, lastIndex)
else:
return
def partition(arr, firstIndex, lastIndex):
i =firstIndex-1
for j in range(firstIndex, lastIndex):
if arr[j]<=arr[lastIndex]:
i=i+1
arr[i],arr[j]=arr[j],arr[i]
arr[i+1],arr[lastIndex]=arr[lastIndex],arr[i+1]
return i
def random_partition(arr,firstIndex, lastIndex):
i=random.randint(firstIndex,lastIndex)
arr[i],arr[lastIndex]=arr[lastIndex],arr[i]
return partition(arr,firstIndex,lastIndex)
if __name__ == '__main__':
arr=random_int_list(1,100000,100)
print("initial array:\n",arr)
oldtime=datetime.datetime.now()
quicksort(arr,0,len(arr)-1)
newtime=datetime.datetime.now()
print("result array:\n",arr)
print(u'运算时间为:%s微秒'%(newtime-oldtime).microseconds)
测试数据
测试数据量 | 时间 |
---|
100 | 433微秒 |
500 | 2284微秒 |
1000 | 4649微秒 |
2000 | 9987微秒 |
3000 | 15336微秒 |
4000 | 20443微秒 |
5000 | 31395微秒 |
100000 | 611790微秒 |
200000 | 484507微秒 |
3.3.中位数排序
代码
import random
import datetime
def random_int_list(start, stop, length):
start, stop = (int(start), int(stop)) if start <= stop else (int(stop), int(start))
length = int(abs(length)) if length else 0
random_list = []
for i in range(length):
random_list.append(random.randint(start, stop))
return random_list
def quicksort(arr):
if not arr:
return []
else:
lst=[arr[0],arr[-1],arr[len(arr)//2]]
div=sorted(lst)[1]
index=arr.index(div)
left=quicksort([l for l in (arr[:index]+arr[index+1:]) if l<=div])
right=quicksort([r for r in (arr[:index]+arr[index+1:]) if r>div])
return left+[div]+right
if __name__ == '__main__':
arr=random_int_list(1,100000,100000)
print("initial array:\n",arr)
oldtime=datetime.datetime.now()
print("result array:\n",quicksort(arr))
newtime=datetime.datetime.now()
print(u'运算时间为:%s微秒'%(newtime-oldtime).microseconds)
测试数据
测试数据量 | 时间 |
---|
100 | 257微秒 |
500 | 1262微秒 |
1000 | 2693微秒 |
2000 | 5659微秒 |
3000 | 8849微秒 |
4000 | 13815微秒 |
5000 | 14782微秒 |
100000 | 409379微秒 |
200000 | 136135微秒 |