[Python]快速排序

最近摸了下Pyhton,发现真心好用。写下快排来练手。

import random
def partition(a,lo,hi):
	i = lo
	j = hi+1
	v = a[lo]
	while True:
		while a[i]<=v:
			i = i+1
			if i == hi:
				break
		j = j-1                 
		while a[j]>v:
			j = j-1
			if j == lo:
				break
		if i>=j:
			break
		a[i],a[j]=a[j],a[i]
	a[lo],a[j] = a[j],a[lo]
	return j	

def quicksort(a,lo,hi):
	if hi<=lo:
		return
	j = partition(a,lo,hi)
	quicksort(a,lo,j-1)
	quicksort(a,j+1,hi)

a = []
for i in range(1000000):
	a.append(random.uniform(1,100000000))
quicksort(a,0,len(a)-1)

写的时候很多小细节要注意,比如要注意切分中j的移动,任何一点对i和j不合适的改动都会导致错误。

100万的数据时间是3.44223299616秒排序完成。

对比下选择排序:1万的数据在6.5秒内排序完成。100万数据时间太长。

def selectionsort(a):
	for i in range(len(a)):
		for j in range(i,len(a)):
			if a[i]>a[j]:
				a[i],a[j]=a[j],a[i]

即使是简单的快速排序也有多种改进方法:

1)存在很多重复元素的时候可以采用3路排序的方法,提高速度;

2)对小数组排序,插入排序比快速排序更快,因为快速排序是递归的。

下面继续修改代码(加入小数组用插入排序):

import random
import time   
def partition(a,lo,hi):
	i = lo
	j = hi+1
	v = a[lo]
	while True:
		while a[i]<=v:
		i = i+1
		if i == hi:
			break
			j = j-1
		while a[j]>v:
			j = j-1
			if i>=j:
				break
				a[i],a[j]=a[j],a[i]
		a[lo],a[j] = a[j],a[lo]
	return j


def quicksort(a,lo,hi):
	f hi>=lo+15:
		j = partition(a,lo,hi)
		quicksort(a,lo,j-1)
		quicksort(a,j+1,hi)
	else:
		selectionsort(a,lo,hi)


def selectionsort(a,lo,hi):
	for i in range(lo,hi+1):
		for j in range(i,hi+1):
			if a[i]>a[j]:
				a[i],a[j]=a[j],a[i]


a = []

for i in range(1000000):
	a.append((int)(random.uniform(1,100000000)))
start = time.clock()  
quicksort(a,0,len(a)-1)
end = time.clock()  
print end-start 
print a[0:10]
100万数据3.56445105976s完成,并没有体现特别大的优势,算法书上说省15%左右的时间,还要仔细再研究下。

对多个重复的元素进行排序:

三相切分

import random
import time
def quick3sort(a,lo,hi):
	if hi<=lo:
		return
	lt = lo
	i = lo+1
	gt = hi
	v = a[lo]
	while i<=gt:
		if a[i]v:
			a[i],a[gt] = a[gt],a[i]
			gt =gt-1
		else:
			i = i+1

	quick3sort(a,lo,lt-1)
	quick3sort(a,gt+1,hi)
a =[]
for i in range(1000000):
	a.append((int)(random.uniform(1,100)))
start = time.clock()
quick3sort(a,0,len(a)-1)
end = time.clock()
print end-start
print a[0:10]
100万数据,范围(1,100000000)。6.12628795802s完成。

三相切分基本思路是把数据分成小于v,等于v,大于v的三段。然后再对小于v和大于v的进行快速排序。

如果对相同元素多的数据比如(1:100)100万组数据只在1.45126854664内完成。

(1:10)的数据只在0.754866314071内完成。

而对原始的quicksort要用3.83970068155,和范围大的时间一样。


实际上如果已知到键的种类,桶排序是最快的,它只需要O(N)的算法复杂度。

你可能感兴趣的:(LeetCode)