<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">BFPRT,通常叫做Median of Medians,一个线性查找算法,关于它的具体介绍可以自行wiki,最近重温几个常见算法,发现好像没有用Python实现的BFPRT算法,所以就自己写了一个。这里算法最终结果是输出数组中第k大的数。</span>
算法步骤:
1. 将输入数组分为若干长度为5的一小组(若数组长度不够5整除,后面零散的可以忽略掉),排序获取中位数,把得到的中位数继续按照这种方法计算,得到最终的中位数,作为快速分割的主元pivot
2. 快速分割,按得到的中位数将数组分成两部分,小于pivot的和大于pivot的, 获取分割后pivot的下标index
3. 判断条件:若k=index,pivot即为输出结果,如若不等,判断k与index的大小关系,决定下一步操作是在小于pivot的部分好是大于pivot的部分(具体见代码)
def partition(arr, pivotIndex):
index = 0
r = len(arr) - 1
pivotValue = arr[pivotIndex]
arr[pivotIndex], arr[r] = arr[r], arr[pivotIndex]
for i in range(0, r+1):
if arr[i] < pivotValue:
arr[index], arr[i] = arr[i], arr[index]
index += 1
arr[index], arr[r] = arr[r], arr[index]
return index
def pivot_median(arr):
n = len(arr)
while n > 5:
cols = n/5
m = []
for i in range(0, cols):
s = sorted(arr[5*i:(5*i+5)])
m.append(s[2])
arr = m
n = len(arr)
arr.sort()
return arr[n/2]
def bfprt(arr, k):
pivot = pivot_median(arr)
pivotIndex = arr.index(pivot)
index = partition(arr, pivotIndex)
n = len(arr)
if k < n - index:
return bfprt(arr[index+1:n], k)
elif k == n - index:
return pivot
elif k > n - index:
return bfprt(arr[0:index], k-(n-index))
能运行之后就没怎么修改代码,所以代码显得有些粗糙。细心的朋友会发现有一个问题就是对于重复出现的数字怎么办,这里没做什么处理,留给各位大神吧
![偷笑](http://static.blog.csdn.net/xheditor/xheditor_emot/default/titter.gif)