BFPRT寻找第top-k元素

参考:https://blog.csdn.net/panglinzhuo/article/details/79795172
BFPRT算法总体思想:
1.将所有n个数据分为n/5(的向下取整)组,每一组有5个元素, 用归并/快速排序求出每一组的中位数(时间复杂度为*5log5 * n/5, 即O(n)),并递归的调用BFPRT算法求出这n/5个中位数的中位数(T(n/5)), 也就是第n/10大的元素,记为m,找到m在原数组中的位置index(O(n))。
2.将原数组以m为分界点,将大于m的num2个元素放在m右边,小于等于m的num1个元素放在m左边,此时m的新位置为index_new
3.把k与num1比较,如果k=num1+1,则说明分界点m就是第k大的元素,如果k<=num1,说明第k大的元素在m左边,接下来去m左边寻找;否则在m右边,应去m右边寻找。这样就将原问题转化为规模更小的问题了。

代码2完全遵循思想,代码1练习

def median(arr):    #返回划分值,即中位数数组的中位数
    if len(arr)<5:
        arr.sort()
        return arr[len(arr)//2]
    else:
        splitnum=len(arr)//5
        mid=[]
        for i in range(splitnum):
           s=sorted(arr[i*5:(i+1)*5])
           mid.append(s[2])
        mid.sort()
        return mid[len(mid)//2]
def parttion(arr,value):  #快排,小于大于等于分开
    xiao=0-1     #小于区域
    da=len(arr)  #大于区域
    i=0
    while i<da:   #条件容易写错
        if arr[i]<value:
            arr[i],arr[xiao+1]=arr[xiao+1],arr[i]
            xiao+=1
            i+=1
        elif arr[i]>value:
            arr[i],arr[da-1]=arr[da-1],arr[i]
            da-=1
        else:
            i+=1
    return xiao,da,arr
def bfprt(arr,k):   #递归调用bfprt
    pivot=median(arr)
    xiao, da, arr=parttion(arr,pivot)
    if da+1>k>xiao+1:                    #注意边界调整
        return pivot
    elif k<=xiao+1:
        return bfprt(arr[0:xiao+1],k)
    elif k>=da+1:
        return bfprt(arr[da:len(arr)],k-da)
arr=[1,3,4,1,7,54,9,5,6,12,11,13,10]
print(bfprt(arr,3))

代码2

def parttion(arr,value):  #快排,小于大于等于分开
    xiao=0-1     #小于区域
    da=len(arr)  #大于区域
    i=0
    while i<da:   #条件容易写错
        if arr[i]<value:
            arr[i],arr[xiao+1]=arr[xiao+1],arr[i]
            xiao+=1
            i+=1
        elif arr[i]>value:
            arr[i],arr[da-1]=arr[da-1],arr[i]
            da-=1
        else:
            i+=1
    return xiao,da,arr
def bfprt(arr,k): 
    if len(arr)<5: #小于5时,直接返回第k个
        arr.sort()
        return arr[k-1]

    splitnum = len(arr) // 5
    mid = []          #中位数数组
    for i in range(splitnum):
        s = sorted(arr[i * 5:(i + 1) * 5])
        mid.append(s[2])

    pivot=bfprt(mid,len(arr)//10)  #递归,求中位数数组的中位数
    
    xiao, da, arr=parttion(arr,pivot)
    if da+1>k>xiao+1:                    #注意边界调整
        return pivot
    elif k<=xiao+1:
        return bfprt(arr[0:xiao+1],k)
    elif k>=da+1:
        return bfprt(arr[da:len(arr)],k-da)
arr=[1,3,4,1,7,54,9,5,6,12,11,13,10]
print(sorted(arr))
print(bfprt(arr,6))
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值