《编程之美》2.5寻找最大的K个数

问题:有很多个无序的数(假设为N个),怎么选出其中最大的K个数?

 

Kay’s word:

kay的理解:“很多” == 好多好多,无法存储,因此首先排除了对输入数排序的解法,而采用小容量数组整理大的输入数据,即:开大小为K的数组,通过遍历N个输入数组,每遍历一个数num,检查K数组的最小数,如果比num小,则用num替换。最终完成K个最大数的提取。

代码如下:

#include <stdio.h> int a[] = {1,8,5,7,6,2,9,5,4,1,2,3,6,5,8,7,1,2,3,8,0,2,5,1,8,9,3,9,6,5,8,2,8,8,6,9,5,2,7,5,8,2,4,6,5,1,3,7,8,5,2,1,3,6,5,8,4,2,6,8}; //int a[] = {1,2,3,4,5,6,7,8,9}; int inputsize =60; //int inputsize =9; int ret[] = {0,0,0,0,0}; int size = 5; void insertRet(int curnum) { int i=0 ; for(i=0;(i<size)&&(curnum!=ret[i]);i++); //检查重复,如有重复,直接退出 if(i<size) return; i=0; int min = ret[0]; int minlocate=0; for(i=1;i<size;i++)//找K数组中的最小值 { if(min > ret[i]) { min = ret[i]; minlocate = i; } } if(curnum > ret[minlocate])//比较最小值与curnum大小,替换 { ret[minlocate]=curnum; } return; } int main() { int i; for(i=0 ; i<inputsize ; i++) { printf(“%d-“,a[i]); } printf(“/n”); int cur = 0; for(cur = 0; cur < inputsize; cur++) { printf(“InSert number : %d/n”,a[cur]); printf(“Previous rets :”); for(i=0; i<size; i++) printf(“%d–“,ret[i]); printf(“/n”); insertRet(a[cur]); printf(“Current retis :”); for(i=0; i<size; i++) printf(“%d–“,ret[i]); printf(“/n”); } system(“pause”); } 

 

insertRet函数代码部分,使用的是:

第一次遍历K数组,检查是否有与待插入的curnum数值相同的数,去重,如果有相同的,直接退出比较;

第二次遍历K数组,找最小数,如果curnum大于最小数,则用curnum代替最小数。

 

一次改进:可改为一次遍历,代码如下:

void insertRet(int curnum) { int i=0 ; int min = 100; int minlocate=size; for(i=0;(i<size)&&(curnum!=ret[i]);i++) { if(min > ret[i]) { min = ret[i]; minlocate = i; } } if(curnum == ret[i]) return; if(curnum > ret[minlocate]) ret[minlocate]=curnum; return; } 

 

二次改进:在K值较大的情况下,简单遍历效率较低O(K),可将其存储为有序序列,再用二分查找O(log2K)来选择curnum的插入位置,但是插入数据之后要对原有数据进行挪动,也会增加开销,尚未实现。。。

 

当时在查找时想到了二叉排序树,或者堆排序,只是空间有限,不利于实现,不过这种插入排序的效率还是很可观的,下次要实现下玩玩

    原文作者:kaytowin
    原文地址: https://blog.csdn.net/kaytowin/article/details/5002594
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞