您的位置:首页 > 其它

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.

伪码如下:

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);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  算法
相关文章推荐