依据快速排序的partition方法, 改进,寻找用于划分的值V
将输入数组划分成n/5组,每组中的有一个中位数,找出所有中位数的中位数,即为V
#coding:utf-8
#最坏情况下O(n)找到第n小的元素
def insert_sort(L, begin, end):
if end>begin:
for i in xrange(begin+1,end+1):
while i > begin:
if L[i-1] > L[i]:
L[i-1], L[i]=L[i], L[i-1]
i -= 1
else:
break
def get_v(L, begin, end):
if end==begin:
return L[begin]
length = end-begin+1
mid=[]
group_num = length/5
remained_num = length%5
for s in xrange(group_num):
index = s*5+begin
insert_sort(L, index, index+4)
mid.append(L[index+2])
if remained_num:
index = begin+group_num*5
insert_sort(L, index, index+remained_num-1)
if remained_num%2==0:
mid.append(L[index-1+remained_num/2])
else:
mid.append(L[index-1+remained_num/2+1])
mid_num = select(mid,0,len(mid)-1,len(mid)/2)
def partition(L, begin, end, v):
'''基于值v快速划分'''
for i in xrange(begin, end+1):
if L[i]==v:
break
L[begin], L[i]=L[i], L[begin]
while end > begin:
while end>begin and L[begin]<=L[end]:
end -= 1
if end>begin :
L[begin], L[end] = L[end], L[begin]
begin += 1
while end > begin and L[begin] <= L[end]:
begin += 1
if end > begin:
L[begin], L[end] = L[end], L[begin]
end -= 1
return begin
def select(L, begin, end, k):
if end>=begin:
v = get_v(L, begin, end) #获取理想的值
index = partition(L, begin, end, v)
le = index-begin+1
if le == k:
return L[index]
elif le > k:
return select(L, begin, index-1, k)
else:
return select(L, index+1, end, k-le)
if __name__ == "__main__":
import sys
L = sys.argv[1:]
if not L:
import random
L = [random.randint(1, 10) for i in xrange(10)]
print L
print select(L,0,len(L)-1,3)