BFPTR算法

来自于Blum、Floyd、Pratt、Rivest、Tarjan这5个人,一起发布了一篇名为 “Time bounds for selection” 的论文,有兴趣可以看一下:https://pan.baidu.com/s/1QEWjZBrjEJ7zTIrI99sFYA。

下面是一种实现方式,这种有一个问题,只是找到中位数了,标号还要搜索然后此时的数组是有结构规律的,划分数组的时候使用的是快排的划分,没有用到这里insert_sort排序产生的局部有序的特征,改进优化方法:在找中位数组中位数的过程中想办法记录下来,哪些数据必定小于中位数的在左上方,那些数据必定大于中位数在右下方, 以及不确定的那一块。

# -*- coding: utf-8 -*-# 简单的插入排序
def insert_sort(arr,low,high):# 指针i,代表第几次插入,第0次,就默认首元素放入有序列表# 从第1次开始,拿一个元素放入有序列表,或者理解为拿原数组里面# 第i个元素放入有序数组,在这里是原地操作的,要么使用交换,要么# 先拿出一个元素在空中,数组里面就流出了一个空位for i in range(low+1,high+1):# 把第i个元素拿起,暂时放在空中temp = arr[i]# 指针j是从尾部扫描已排列的有序数组,注意有序列表是从小到大排列的# j一直都是指在空闲的位置的j = i# 遇到比空中的元素大的元素,大的元素后移一位,移到空出来的那个位置# 此时就又空出来一个位置,更新空闲的位置j,...直到碰到比空中的元素小的元素# 空中元素的位置就找到了,就是现在j指的空闲位置while arr[j-1] > temp and j >low:arr[j] = arr[j-1]j -=1# 把空中元素放入空闲位置arr[j] = temp# 这个一个可以准确找到中位数的算法?显然不是的这个只是大概找中位数的方法,而且还有一个
# 致命的问题,只是找到中位数了,标号还要搜索
# 然后此时的数组是有结构规律的,划分数组的时候使用的是快排的划分,没有用到这里面
# insert_sort排序产生的局部有序的特征,改进优化方法:在找中位数组中位数的过程中
# 想办法记录下来,哪些数据必定小于中位数的在左上方,那些数据必定大于中位数在右下方,
# 以及不确定的那一块
def findMid(arr,low,high):
###############################################################################
# Divide
###############################################################################    # 这里的两个指针为每个小分组的头和尾,也可以只用一个指针left = lowright = low+4# count指的是中位数数组的指针count = 0# 当小数组的尾指针小于等于右边界限时,对每个小组排序,得到每个小组的中位数while right <= high:insert_sort(arr,left,right)# 因为中位数是分散的步长为5,对于我来说不好处理,所以此时处理时把中位都放在数组的# 前面,这样下一轮时就比较好处理了,但是这样处理,就破坏了数组有序的规律,让最后# 无法利用数组的有序规律来划分数据,这里可以优化arr[low + count],arr[left +2] = arr[left +2],arr[low + count]# 处理下一组left +=5right +=5# 记得更新中位数数组的指针count +=1# 当跳出循坏时,就需要处理余数,或者没有进入循环,也要处理余数# 把余数排序,获取中位数,加入到中位数列表if left <=high:insert_sort(arr,left,high)arr[low + count],arr[left+(high-left)//2] = arr[left+(high-left)//2],arr[low + count]count +=1# 以上过程是这个问题划分子问题的过程,也就是partion的过程,也就是把问题规模n变成# n//5的过程。
###############################################################################
# Conquer
################################################################################获取到中位数数组,得到了子问题,下面就考虑治conquer了# 第一种情况,数组没有经过5分组,排序后直接到这里,直接返回在首位的中位数,这种情况下count=1# 当进入了5分组没有进入余数处理,这时count=1,也应该是返回首元素# 其他情况count>=0时,这两个元素还没有排序,所以要进入下一轮排序一下,变成count=1输出首元素# count就是low>high的情况,直接返回空if count ==0:returnif count ==1:return arr[low]else:# 注意count是指中位数元素的数量,对应数组上的指针需要-1return findMid(arr,low,low+count-1)#标号需要通过检索得到
def findIndex(arr,mid):for i in range(len(arr)):if arr[i] == mid:return idef partion_with_index(arr,low,high,index):def partition(arr,low,high):# 这时另外一种考虑方式,而且他是不需要额外空间的,他只使用一个指针来区分小于基准和大于基准的# pointer_less_than代表这个指针的左边全部都是小于基准的(包括自己,不包括首元素)# 然后从左往右扫描,遇到小于基准的元素,就把小于基准元素区域的后面紧接着的一个元素和他交换# 那么小于基准元素区域就多了一个元素,。。。就这样小于基准的元素就连在了一起# 首元素是基准元素,小于基准元素区域块,大于基准元素区域块,现在分成了三个部分# 把首元素和小于基准元素区域块最后一个元素交换,那三部分就变成,小于的,基准,大于的# 刚开始小于基准的元素为0,暂且指向首位值pointer_less_than = low# 然后一次扫描后面所有元素for i in range(pointer_less_than +1,high+1):# 遇到小于基准的,就把小于基准元素区域的后面紧接着的一个元素和他交换,小于的块相当于也更新了if arr[i] < arr[low] :pointer_less_than +=1arr[pointer_less_than],arr[i]=arr[i],arr[pointer_less_than]#  把首元素和小于基准元素区域块最后一个元素交换,那三部分就变成,小于的,基准,大于的       arr[low],arr[pointer_less_than] = arr[pointer_less_than],arr[low]return pointer_less_thanarr[low],arr[index] = arr[index],arr[low]return partition(arr,low,high)def BFPTR(arr,low,high,k):
######################################################################### divide
######################################################################### 首先获取midmid = findMid(arr,low,high)# 获取此时mid的indexmid_index = findIndex(arr,mid)# 根据mid来划分数据,返回的是中间的index(就是排序后最终的位置)index =partion_with_index(arr,low,high,mid_index)
######################################################################## Conquer
########################################################################    #根据index做出子问题的处理if index == k:return arr[index]elif index > k:return BFPTR(arr,low,index-1,k)else:return BFPTR(arr,index+1,high,k)arr3 = [7,3,66,33,22,66,9,0,1,11,14,17,9,10,13,99,44,33,77,88,99,101,404,87,44,22,11,99,43,22]
print(sorted(arr3))
print(BFPTR(arr3,0,len(arr3)-1,(len(arr3)-1)//2-1))
runfile('D:/share/test/BFPTR.py', wdir='D:/share/test')
[0, 1, 3, 7, 9, 9, 10, 11, 11, 13, 14, 17, 22, 22, 22, 33, 33, 43, 44, 44, 66, 66, 77, 87, 88, 99, 99, 99, 101, 404]
22

分治法:BFPTR算法找第k小相关推荐

  1. 找中位数,找第k小,还存在问题

    找第k小 上次介绍了找第二大使用的方法时,使用锦标赛的方法,找到最大,在最大的手下败将里找第二大,也就是亚军在冠军的手下败将里产生,亚军只败给过冠军,这种方法比较次数时(n-1) + (logn-1) ...

  2. 快速排序算法的实现 随机生成区间里的数 O(n)找第k小 O(nlogk)找前k大...

    思路:固定一个数,把这个数放到合法的位置,然后左边的数都是比它小,右边的数都是比它大 固定权值选的是第一个数,或者一个随机数 因为固定的是左端点,所以一开始需要在右端点开始,找一个小于权值的数,从左端 ...

  3. java快排,找第K小的数,找前K个数

    import java.util.Random;public class Main {//时间复杂度,即步骤数public static int sum =0;public static void m ...

  4. 7-1 找第k小的数(反思),a++和++a的区别,运算符优先级,递归分制思想

    作者 陈晓梅 单位 广东外语外贸大学 设计一个平均时间为O(n)的算法,在n(1<=n<=1000)个无序的整数中找出第k小的数. 提示 函数int partition(int a[],i ...

  5. 7-1 找第k小的数 (20 分)

    设计一个平均时间为O(n)的算法,在n(1<=n<=1000)个无序的整数中找出第k小的数. 提示:函数int partition(int a[],int left,int right)的 ...

  6. 算法-寻找第k小元素(C)

    序言 刚开始我认为,寻找第k小的元素:简单呀,先对所有元素排序,之后再找不就完事啦,这时时间复杂度在O(nlgn).那有没有更好的排序的方法了呢?答案:当然是有的. 算法基本思路: (1) 当规模小于 ...

  7. Hoare选择算法 寻找第k小元素C实现 算法的“AWK脚手架和grap运行过程分析”

    现实生活中常有找"最大"."最小"及"中位数"等需求,解决这样的问题不用将整个序列排序.寻找"最大"."最小& ...

  8. 从2个有序数组中找第k小那个数

    系列文章目录 提示:AC==accepted,即LeetCode上提交代码通过,我刷题的代码用的是java,但是C++一个道理,算法思想一样,而且c++和java非常类似,python需要自己写,但是 ...

  9. 分治算法 求第k小元素 O(n) O(nlog2^n)

    BFPRT算法:时间复杂度O(n)求第k小的数字(分治算法+快排) 各位小伙伴,由于本篇文章代码太过杂乱.我于 2018年12月25日 对文中介绍的算法进行了重写.点击上面的蓝色字体,可以阅读重写后的 ...

最新文章

  1. android 实现 下拉筛选的效果
  2. LeetCode-106-Construct Binary Tree from Inorder and Postorder Traversal
  3. Spring Boot 集成 Apollo 配置中心,真香、真强大!
  4. python 打印数组变量_使用Python将数组的元素导出到变量中(unpacking)
  5. DIY穷人版谷歌眼镜,自定义手势操控,树莓派再一次被开发新玩法
  6. linux ftp下载文件_Linux系统中10个使用Wget命令下载文件示例
  7. 第二部分Calendar原理和思想
  8. python pandas series想赋予新的值_Python-pandas根据其他列的值创建新列/逐行应用多列的功能...
  9. jdk32位安装包下载_premiere pro 2017 软件下载及安装教程
  10. cmd(批处理脚本)实现批量下载图片
  11. windows 环境下 0x色彩对应表
  12. 打开caj文件显示服务器忙,欢迎使用CAJViewer-常见问题
  13. ET和LT的原理和区别
  14. redis集群和redis宕机处理方案
  15. 怎样查找计算机死机日志,死机和日志错误
  16. 数据库系统实践 III 查询语句
  17. matlab RBF神经网络对iris鸢尾花数据集进行分类
  18. 转:不懂这些,你所谓的“复盘”都是无用功
  19. java手电筒源码_android平台手电筒开发源代码
  20. 如何在官网选择JAVA版本进行下载

热门文章

  1. oclick vue 传参 函数_详解Vue计算属性和侦听属性
  2. 富文本框让最大四百像素_Django2.0.4 结合 KindEditor 4.1.11 富文本编辑器
  3. 优化 最长上升子序列_LIS - 最长上升子序列 (二分优化)
  4. android调用flutter aar_Flutter原生混合开发
  5. eclipse android开发环境搭建_聊聊Spring boot2.X开发环境搭建和基本开发
  6. python编辑器_python编辑器,作为小白该如何抉择?
  7. 【Get 以太坊技能】CentOS 7 安装 go
  8. java获取数据库MetaData
  9. php+字符串去掉反斜杠,PHP如何去掉反斜杠?
  10. shell+mysql获取数据库名_shell操作mysql数据库