需求

从一亿个数据中,找出其中最小的10个数。

分析

最笨的方法就是将这一亿个数据,按从小到大进行排序,然后取前10个。这样的话,即使使用时间复杂度为nlogn的快排或堆排,由于元素会频繁的移动,效率也不会是最高的。

实际上我们可以维护一个大小为10的大顶堆,开始可以就将数列中的前10个数用来建堆,根元素最大。之后遍历剩余的数,分别将其与根元素进行比较,只要小于根元素,就将该数替代原来的根元素,成为新的根元素,之后adjustdown该堆,则该堆的根元素又是堆中最大的数据了。

测试代码如下

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h> static void show(int *arr, int len)
{
int index;
for(index = 0; index < len; index++)
{
printf("%d ",arr[index]);
}
printf("\n");
} static void swap(int *left, int *right)
{
int tmp = *left;
*left = *right;
*right = tmp;
} void adjustdown(int *arr, int i, int end)
{
int key = arr[i];
int p = i;
int left = 2 * p + 1;
/* 越界就是没孩子 */ /* 只要能进循环,一定有左孩子 */
while( left <= end )
{
/* 有右孩子的情况下,大于等于左右孩子不用换 */
if( (key >= arr[left]) && (left+1 <= end && key >= arr[left+1]))
{
break;
}else if( key >= arr[left] && left + 1 > end) /* 没有右孩子,只有左孩子,且大于等于左孩子不用换*/
{
break;
}else if(left + 1 <= end && arr[left+1] >= arr[left] && key < arr[left+1]) /* 与右孩子换。要保证有右孩子,且右孩子大于等于左孩子,父亲小于右孩子 */
{
swap(arr+p, arr+left+1);
p = left + 1; //父亲与谁换,就到谁的位置了
left = 2 * p + 1;//父亲新的左孩子的位置
}else if(left + 1 <= end && arr[left] > arr[left + 1] && key < arr[left])/* 与左孩子换。有右孩子的情况下,右孩子小于左孩子,父亲小于左孩子 */
{
swap(arr + p, arr + left);
p = left;
left = 2 * p + 1;
}else if(left + 1 > end && arr[left] > key) /* 与左孩子换。没右孩子的情况下,只需父亲小于左孩子 */
{
swap(arr + p, arr + left);
p = left;
left = 2 * p + 1;
}
}
} void heap_sort(int *arr, int len)
{
int p; // 最后一个父亲
int end; // 最后一个有效下标
/* 建一个大顶堆,从最后一个父亲开始调 */
for(p = (len -1 -1) /2 ; p >= 0; p--)
{
adjustdown(arr, p ,len - 1);
}
/* 根结点的值最大,与末尾交换,并继续建立堆结构,再交换... */
for(end = len - 1; end >= 1; end--)
{
swap(arr, arr + end ); // end已经是最大值
adjustdown(arr,0,end-1); // 从arr+1 到 end-1位置都是满足堆结构的
}
} void my_top(int *arr, int len, int top, int *arr_top, int top_len) //此处选最小的top个数,维护大堆。如果是最大top个数,就维护小堆。
{
/* 开始用插入排序 */ /* 不用插入排序,对arr_top直接建堆也是可以的 */
int index;
int pos;
for(index = 0; index < len; index ++)
{
if(index < top)
{
if(index == 0)
{
arr_top[index] = arr[index];
}else
{
/* 插入排序 */
//int pos; 从大到小
for(pos = index - 1; pos >= 0; pos--)
{
if(arr[index] >= arr_top[pos])
{
arr_top[pos + 1] = arr_top[pos];
}else
{
break;
}
}
arr_top[pos+1] = arr[index];
}
}else
{
if(arr[index] >= arr_top[0]) //比最大值还大,说明不是最小的10个数
{
continue;
}else
{
arr_top[0] = arr[index]; //淘汰掉原来最大的
adjustdown(arr_top,0,top_len-1); //重新选最大值 复杂度nlogn 但是这10个数并不是有序的
}
}
}
} int main(int argc, char *argv[])
{
int index;
int arr[20];
int arr_top[5];
memset(arr,0,20);
srand(time(NULL));
for(index = 0; index < 20; index++)
{
arr[index] = rand()%50+1;
}
show(arr,20); heap_sort(arr,20);
show(arr,20); my_top(arr,20,5,arr_top,5);
show(arr_top,5); system("pause");
return 0;
}

最新文章

  1. 【转】oracle中in和exists的区别
  2. 准备 LVM Volume Provider - 每天5分钟玩转 OpenStack(49)
  3. 关于Jquery的delegate绑定事件无效
  4. 【HDU 2577】How to Type
  5. ContentType 属性 MIME
  6. Java跨域设置
  7. 第八十二节,CSS3过渡效果
  8. jQuery 评分插件(转)
  9. C++ STL list详解
  10. TensorRT&amp;Sample&amp;Python[fc_plugin_caffe_mnist]
  11. ionic2项目中实现md5加密
  12. 第一二次java实训作业
  13. java基本数据类型的范围
  14. 胡乱摸的NOIP2017游记和总结
  15. 20155314 2016-2017-2 《Java程序设计》实验四 Android程序设计
  16. nyoj-----前缀式计算
  17. windows系统IIS服务安装
  18. 上传图片Security Error
  19. Cheatsheet: 2017 06.01 ~ 06.30
  20. 微信小程序 - 为何setData到页面上有的加分号

热门文章

  1. hdu 2579 Dating with girls(2)
  2. Javascript是一个事件驱动语言
  3. [转]linux时间同步
  4. params关键字
  5. hmmer 使用(转载)
  6. java中字符串String 转 int(转)
  7. mvc5引用ExtJS6
  8. M1事后分析报告(Postmortem Report)
  9. 程序开发心理学阅读笔记——第I篇
  10. .net之XML