一亿数据获取前100个最大值(基于最小堆和Quicksort)
2012-09-24 10:23
507 查看
前言:
在CSDN上看到一个网友利用最小堆实现 “ 获取一亿数据获取前100个最大值” 。原帖请看:http://blog.csdn.net/yjflinchong/article/details/7533972。
然后自己利用quicksort的原理也写了一个程序来解决那个问题。通过测试,基于quicksort原理的方法平均运行时间是1.264秒,基于最小堆方法的平均运行时间是0.288秒 (网友写的程序运行时间比我的大很多,0.288秒这个程序是我自己写的,如果测试网友写的基于minHeap的方法,运行时间是2.501秒)。基于最小堆方法运行时间很稳定(每次运行时间相差很小),基于quicksort原理的方法运行时间不稳定(每次运行时间相差大)。
基于quicksort实现的原理如下:
1. 假设数组为 array
(N = 1 亿),首先利用quicksort的原理把array分成两个部分,左边部分比 array[N - 1] (array中的最后一个值,即pivot) 大, 右边部分比pivot 小。然后,可以得到 array[array.length - 1] (即 pivot) 在整个数组中的位置,假设是 k.
2. 如果 k 比 99 大,原数组变成了 array [0, ... k - 1], 然后在数组里找前 100 最大值。 (继续递归)
3. 如果 k 比 99 小, 原数组变成了 array [k + 1, ..., N ], 然后在数组里找前 100 - (k + 1) 最大值。(继续递归)
4. 如果 k == 99, 那么数组的前 100 个值一定是最大的。(退出)
代码如下:
下面是基于minHeap写的程序。如果你懂heap sort,那么下面的程序很容易理解。
public class TopHundredHeap {
public static void main(String[] args) {
// the size of the array
int number = 100000000;
// the top k values
int k = 100;
// the range of the values in the array
int range = 1000000001;
//input for minHeap based method
int[] array = new int[number];
Random random = new Random();
for (int i = 0; i < number; i++) {
array[i] = random.nextInt(range);
}
TopHundredHeap thh = new TopHundredHeap();
long t1, t2;
//start time
t1 = System.currentTimeMillis();
int[] top = thh.topHundred(array, k);
//end time
t2 = System.currentTimeMillis();
System.out.println("The total execution time of " +
"quicksort based method is " + (t2 - t1) +" millisecond!");
// print out the top k largest values in the top array
System.out.println("The top "+ k + "largest values are:");
for (int i = 0; i < k; i++) {
System.out.println(top[i]);
}
}
public int[] topHundred(int[] array, int k) {
// the heap with size k
int[] top = new int[k];
for (int i = 0; i < k; i++) {
top[i] = array[i];
}
buildMinHeap(top);
for (int i = k; i < array.length; i++) {
if (top[0] < array[i]) {
top[0] = array[i];
minHeapify(top, 0, top.length);
}
}
return top;
}
// create a min heap
public void buildMinHeap(int[] array) {
int heapSize = array.length;
for (int i = array.length / 2 - 1; i >= 0; i--) {
minHeapify(array, i, heapSize);
}
}
/// MinHeapify is to build the min heap from the 'position'
public void minHeapify(int[] array, int position, int heapSize)
{
int left = left(position);
int right = right(position);
int minPosition = position;
if (left < heapSize && array[left] < array[position]) {
minPosition = left;
}
if (right < heapSize && array[right] < array[minPosition]) {
minPosition = right;
}
if (position != minPosition) {
swap(array, position, minPosition);
minHeapify(array, minPosition, heapSize);
}
}
public void swap(int[] array, int i, int j) {
int temp = array[i];
array[i] = array[j];
array[j] = temp;
}
/// return the left child position
public int left(int i)
{
return 2 * i + 1;
}
/// return the right child position
public int right(int i)
{
return 2 * i + 2;
}
}时间复杂度分析:
基于minheap方法 的时间复杂度是 O(lg K * N), 基于quicksort 方法的平均时间复杂度是 O(N),但是最差是O(N^2). 这也是为何基于quicksort 方法它的时间不稳定的原因。
转载请注明出处:http://blog.csdn.net/beiyeqingteng.
在CSDN上看到一个网友利用最小堆实现 “ 获取一亿数据获取前100个最大值” 。原帖请看:http://blog.csdn.net/yjflinchong/article/details/7533972。
然后自己利用quicksort的原理也写了一个程序来解决那个问题。通过测试,基于quicksort原理的方法平均运行时间是1.264秒,基于最小堆方法的平均运行时间是0.288秒 (网友写的程序运行时间比我的大很多,0.288秒这个程序是我自己写的,如果测试网友写的基于minHeap的方法,运行时间是2.501秒)。基于最小堆方法运行时间很稳定(每次运行时间相差很小),基于quicksort原理的方法运行时间不稳定(每次运行时间相差大)。
基于quicksort实现的原理如下:
1. 假设数组为 array
(N = 1 亿),首先利用quicksort的原理把array分成两个部分,左边部分比 array[N - 1] (array中的最后一个值,即pivot) 大, 右边部分比pivot 小。然后,可以得到 array[array.length - 1] (即 pivot) 在整个数组中的位置,假设是 k.
2. 如果 k 比 99 大,原数组变成了 array [0, ... k - 1], 然后在数组里找前 100 最大值。 (继续递归)
3. 如果 k 比 99 小, 原数组变成了 array [k + 1, ..., N ], 然后在数组里找前 100 - (k + 1) 最大值。(继续递归)
4. 如果 k == 99, 那么数组的前 100 个值一定是最大的。(退出)
代码如下:
public class TopHundredQuickSort { public void tophundred(int[] array, int start, int end, int k) { int switchPointer = start; int pivot = array[end]; //array最后一个值作为pivot for (int i = start; i < end; i++) { if (array[i] >= pivot) { swap(array, switchPointer, i); switchPointer++; } } swap(array, end, switchPointer);//交换后,array左边的值比pivot大,右边的值比pivot小 if (switchPointer < k - 1) { tophundred(array, switchPointer + 1, end, k - switchPointer - 1); } else if (switchPointer == k - 1) { return; } else { tophundred(array, 0, switchPointer - 1, k); } } public void swap(int[] array, int i, int j) { int temp = array[i]; array[i] = array[j]; array[j] = temp; } public static void main(String[] args) { // the size of the array int number = 100000000; // the top k values int k = 100; // the range of the values in the array int range = 1000000001; //input for minHeap based method int[] array = new int[number]; Random random = new Random(); for (int i = 0; i < number; i++) { array[i] = random.nextInt(range); } TopHundredQuickSort topHundred = new TopHundredQuickSort(); //start time long t1 = System.currentTimeMillis(); topHundred.tophundred(array, 0, array.length - 1, k); //end time long t2 = System.currentTimeMillis(); System.out.println("The total execution time " + "of quicksort based method is " + (t2 - t1) +" millisecond!"); // print out the top k largest values in the top array System.out.println("The top "+ k + "largest values are:"); for (int i = 0; i < k; i++) { System.out.println(array[i]); } } }
下面是基于minHeap写的程序。如果你懂heap sort,那么下面的程序很容易理解。
public class TopHundredHeap {
public static void main(String[] args) {
// the size of the array
int number = 100000000;
// the top k values
int k = 100;
// the range of the values in the array
int range = 1000000001;
//input for minHeap based method
int[] array = new int[number];
Random random = new Random();
for (int i = 0; i < number; i++) {
array[i] = random.nextInt(range);
}
TopHundredHeap thh = new TopHundredHeap();
long t1, t2;
//start time
t1 = System.currentTimeMillis();
int[] top = thh.topHundred(array, k);
//end time
t2 = System.currentTimeMillis();
System.out.println("The total execution time of " +
"quicksort based method is " + (t2 - t1) +" millisecond!");
// print out the top k largest values in the top array
System.out.println("The top "+ k + "largest values are:");
for (int i = 0; i < k; i++) {
System.out.println(top[i]);
}
}
public int[] topHundred(int[] array, int k) {
// the heap with size k
int[] top = new int[k];
for (int i = 0; i < k; i++) {
top[i] = array[i];
}
buildMinHeap(top);
for (int i = k; i < array.length; i++) {
if (top[0] < array[i]) {
top[0] = array[i];
minHeapify(top, 0, top.length);
}
}
return top;
}
// create a min heap
public void buildMinHeap(int[] array) {
int heapSize = array.length;
for (int i = array.length / 2 - 1; i >= 0; i--) {
minHeapify(array, i, heapSize);
}
}
/// MinHeapify is to build the min heap from the 'position'
public void minHeapify(int[] array, int position, int heapSize)
{
int left = left(position);
int right = right(position);
int minPosition = position;
if (left < heapSize && array[left] < array[position]) {
minPosition = left;
}
if (right < heapSize && array[right] < array[minPosition]) {
minPosition = right;
}
if (position != minPosition) {
swap(array, position, minPosition);
minHeapify(array, minPosition, heapSize);
}
}
public void swap(int[] array, int i, int j) {
int temp = array[i];
array[i] = array[j];
array[j] = temp;
}
/// return the left child position
public int left(int i)
{
return 2 * i + 1;
}
/// return the right child position
public int right(int i)
{
return 2 * i + 2;
}
}时间复杂度分析:
基于minheap方法 的时间复杂度是 O(lg K * N), 基于quicksort 方法的平均时间复杂度是 O(N),但是最差是O(N^2). 这也是为何基于quicksort 方法它的时间不稳定的原因。
转载请注明出处:http://blog.csdn.net/beiyeqingteng.
相关文章推荐
- 算法兴趣----- 一亿数据获取前100个最大值(仅供参考,基于快速排序的实现时间不稳定,基于最小堆实现。如果我们只要求前K个最大(小)值的时候,用堆是最好的选择,因为这里不用每次都排序了)
- 一亿数据获取前100个最大值(利用quicksort的原理实现)
- 一亿数据获取前100个最大值(利用quicksort的原理实现) [# 70]
- 算法2— 一亿数据获取前100个最大值
- 获取一亿数据获取前100个最大值
- 3秒搞定!~~ 一亿数据获取前100个最大值
- 获取一亿数据获取前100个最大值
- 3秒搞定!~~ 一亿数据获取前100个最大值
- 3秒搞定!~~ 一亿数据获取前100个最大值
- 腾讯面试题:一亿数字获取前100个最大的数字办法
- 腾讯面试题:一亿数字获取前100个最大的数字办法
- 一亿数据获取最大值的前100位
- 基于ROS平台的移动机器人-6-使用Kinect2获取激光数据
- 经典算法应用之七----10亿数据中取最大的100个数据
- 基于vue-cli及express模拟Ajax获取服务器数据
- 基于随机采样获取训练、测试数据示例(Python)
- 算法跨语言/*从一维数组100个数据中选出最大10个数的下标及最小6个数的下标*/
- C#应用GDAL通过传入范围获取tif数据的最大高程值及其坐标
- C#调用TeeChart显示数据,当放大时,怎样当前图表中获取X轴的最小值和最大值
- 最简单的获取一组数据中的最大和最小数