BFPRT算法过程分析和实现
2017-08-01 13:05
127 查看
过程分析
参考自王晓东 《计算机算法设计与分析(第三版)》
BFPRT算法是一个最坏情况下用O(n)时间就可以找到TopK元素的算法。
过程分析如下:
(1)将n个元素分成n/5个组,除了可能最后一组不是5个元素外,每组5个元素。用任意一种排序算法,将每组元素排好序,并取每组的中位数共n/5个.
(2)找出这n/5个元素中的中位数。然后以这个元素作为划分基准。
可以分析出,在这种情况下,找出的基准x至少比1/2*(n/5 - 1)* 3个元素要大,也即至少比3*((n-5)/10)个元素要大,同理x也至少比3*((n-5)/10)个元素要小。而当n >= 75时,3((n-5)/10) >= n/4。所以按此基准划分所得的两个子数组的长度都至少缩短1/4.
伪码如下:
代码实现如下:
参考自王晓东 《计算机算法设计与分析(第三版)》
BFPRT算法是一个最坏情况下用O(n)时间就可以找到TopK元素的算法。
过程分析如下:
(1)将n个元素分成n/5个组,除了可能最后一组不是5个元素外,每组5个元素。用任意一种排序算法,将每组元素排好序,并取每组的中位数共n/5个.
(2)找出这n/5个元素中的中位数。然后以这个元素作为划分基准。
可以分析出,在这种情况下,找出的基准x至少比1/2*(n/5 - 1)* 3个元素要大,也即至少比3*((n-5)/10)个元素要大,同理x也至少比3*((n-5)/10)个元素要小。而当n >= 75时,3((n-5)/10) >= n/4。所以按此基准划分所得的两个子数组的长度都至少缩短1/4.
伪码如下:
Type Select(Type[] a, int p, int r, int k) { if((r-p) < 75) { 对数组a[p:r]排序; return a[p+k-1]; } for(int i = 0; i <= (r-p+1-5)/5) { 将a[p+5*i]至a[p+5*i+4]的第三小元素与a[p+i]交换位置;//思考这步是干嘛的 } //找中位数的中位数,r-p-4就是n-5 Type x = Select(a, p, p + (r - p - 4) / 5, (r - p - 4) / 10); int i = Patition(a, p, r, x),j = i - p + 1; if(k <= j) return Select(a, p, i, k); else return Select(a, i + 1, r, k - j); }
代码实现如下:
import java.util.Arrays; import java.util.Scanner; /* @author 作者 E-mail: * @date 创建时间:2017年8月1日 上午11:40:56 * @version 1.0 * @parameter * @since * @return */ public class BFPRT { public static int Select(int[] a, int p, int r, int k) { if (r - p < 75) { Arrays.sort(a); return a[p + k - 1]; } for (int i = 0; i <= (r - p + 1 - 5) / 5; i++) { int temp = a[i]; swap(5 * i, 5 * i + 4, 3, a); } int x = Select(a, p, p + (r - p + 1 - 5) / 5, (r - p + 1 - 5) / 10);// 中位数的中位数 int i = Partition(a, p, r, x), j = i - p + 1; if (k <= j) return Select(a, p, i, k); else return Select(a, i + 1, r, k - j); } public static void swap(int begin, int end, int minThird, int[] a) { Arrays.sort(a, begin, end); int temp = a[begin]; a[begin] = a[begin + minThird]; a[begin + minThird] = temp; } public static int Partition(int[] a, int p, int r, int partValue) { // 相当于快速排序的中的一趟 int pivot = partValue; int partValueId = FindpartValueId(a, partValue); a[partValueId] = a[0]; a[0] = pivot; int left = p; int right = a.length - 1; while (left < right) { while (a[right] > pivot) right--; a[left] = a[right]; while (a[left] < pivot) left++; a[right] = a[left]; } a[left] = a[0]; return left; } public static int FindpartValueId(int[] a, int partValue) { int i; for (i = 0; i < a.length; i++) { if (a[i] != partValue) continue; else break; } return i; } public static void main(String[] args) { // TODO Auto-generated method stub int[] a = { 12, 76, 29, 22, 15, 62, 29, 58, 35, 67, 58, 33, 28, 89, 90, 28, 64, 48, 20, 77 }; Scanner sc = new Scanner(System.in); int k = sc.nextInt(); int minKth = Select(a, 0, a.length - 1, k); System.out.println(minKth); } }
相关文章推荐
- Spring3.1.0实现原理分析(九).AOP创建代理对象的过程
- Luncher修改wallpaper(壁纸)源码跟踪(代码实现过程分析)
- 常用加密解密技术之——【DES算法实现过程分析】
- 关于Ext3.0中按条件查询并重新加载Grid中的数据的实现过程及store.load的分析
- malloc 实现过程分析二
- 编译原理(八) 算符优先分析法(分析过程的算法和C++实现)
- 业务审批过程分析与使用Sbo系统存储过程实现业务审批流程状态检索
- linux路由内核实现分析(三)---路由查找过程
- 电影网站增删改查-4 spring boots/MVC/neo4j/thymeleaf 源码分析 实现View 新增过程
- linux伙伴算法实现过程分析
- 面向过程就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了;面向对象是把构成问题事务分解成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描叙某个事物在整个解决问题的步骤中的行为(转)
- 实现数据库同步备份 过程--结果---分析
- freemarker日志实现过程分析
- 加密算法(三)——【MD5算法实现过程分析】
- node中javascript调用c++实现过程分析
- 第二人生的源码分析(10)登录授权的实现过程
- 一个分析“文件夹”选择框实现方法的过程
- elk实时日志分析平台部署搭建详细实现过程
- 分析一个通用的rtsp server实现过程基础模块
- OpenStack建立实例完整过程源码详细分析(12)----依据AMQP通信架构实现消息发送机制解析之一