100亿个数取前1w名

#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/time.h>

static unsigned int BUF_PAGES;          /* 缓冲区有多少个page */
static unsigned int PAGE_SIZE;          /* page的大小 */
static unsigned int BUF_SIZE;           /* 缓冲区的大小, BUF_SIZE = BUF_PAGES*PAGE_SIZE */

static int *buffer;                                     /* 输入缓冲区 */
static int *heap;                                       /* 最小堆 */

long get_time_usecs();
void init_heap(int n);
void adjust(int n, int i);

int main(int argc, char **argv)
{
        unsigned int            K, idx, length;
        int                                     fd, i, bytes, element;

        long start_usecs = get_time_usecs();

        fd = open(argv[1], O_RDONLY);
        if (fd < 0) {
                printf("can‘t open file %s\n",argv[1]);
                exit(0);
        }

        PAGE_SIZE = 4096;                                                       /* page = 4KB */
        BUF_PAGES = 512;
        BUF_SIZE = PAGE_SIZE*BUF_PAGES;                         /* 4KB*512 = 2M */
        buffer = (int *)malloc(BUF_SIZE);
        if (buffer == NULL) exit(0);

        K = atoi(argv[2]);
        heap = (int *)malloc(sizeof(int)*(K+1));
        if (heap == NULL) {
                free(buffer);
                exit(0);
        }

        bytes = read(fd, heap+1, K*sizeof(int));
        if (bytes < K*sizeof(int)) {
                printf("data size is too small\n");
                exit(0);
        }
        init_heap(K);

        idx = length = 0;
        for (;;) {
                if (idx == length) {    // 输入缓冲区用完
                        bytes = read(fd, buffer, BUF_SIZE);
                        if (bytes == 0) break;
                        length = bytes/4;
                        idx = 0;
                }
                //从buffer取出一个数,若比最小堆堆顶元素大,则替换之
                element = buffer[idx++];
                if (element > heap[1]) {
                        heap[1] = element;
                        adjust(K, 1);
                }
        }

        long end_usecs = get_time_usecs();

        printf("the top %d numbers are: \n", K);
        for (i = 1; i <= K; i++) {
                printf("%d ", heap[i]);
                if (i % 6 == 0) {
                        printf("\n");
                }
        }
        printf("\n");

        free(buffer);
        free(heap);
        close(fd);

        double secs = (double)(end_usecs - start_usecs) / (double)1000000;
        printf("program tooks %.02f seconds.\n", secs);

        return 0;
}

void init_heap(int n)
{
        int             i;

        for (i = n/2; i > 0; i--) {
                adjust(n, i);
        }
}

/* 节点i的左子树和右子树已是最小堆, 此函数的
 * 作用是把以节点i为根的树调整为最小堆 */
void adjust(int n, int i)
{
        heap[0] = heap[i];
        i = 2 * i; //左子节点
        while (i <= n) {
                if (i < n && heap[i+1] < heap[i]) {
                        i++;  //左右节点小的那个进行比较
                }
                if (heap[i] >= heap[0]) {
                        break;
                }
                heap[i / 2] = heap[i]; //左右节点都比根节点大 将较小的节点上移
                i = i * 2; //锁定到下一层节点
        }
        heap[i / 2] = heap[0]; //找到合适位置 进行更换
}

long get_time_usecs()
{
        struct timeval time;
        struct timezone tz;
        memset(&tz, ‘\0‘, sizeof(struct timezone));
        gettimeofday(&time, &tz);
        long usecs = time.tv_sec*1000000 + time.tv_usec;

        return usecs;
}

编译:  g++ -o main main.cpp

产生测试数据: dd if=/dev/urandom of=random.dat bs=1M count=1024

运行: ./main random.dat 100

算法复杂度:  nlog10000

时间: 2024-10-21 14:27:22

100亿个数取前1w名的相关文章

1亿个数选前100最大数

算法思想 1.选择一亿数的前100数前100个数排序 2.后面的数字通过插入排序 #include<iostream> using namespace std; void buddlesort(int array[],int n) { bool exchange=true; int count=n; while(exchange){ exchange=false; for(int i=0;i<count;i++) { if(array[i]>array[i+1]) { int te

100亿个数字找出最大的10个

1.首先一点,对于海量数据处理,思路基本上是确定的,必须分块处理,然后再合并起来. 2.对于每一块必须找出10个最大的数,因为第一块中10个最大数中的最小的,可能比第二块中10最大数中的最大的还要大. 3.分块处理,再合并.也就是Google MapReduce 的基本思想.Google有很多的服务器,每个服务器又有很多的CPU,因此,100亿个数分成100块,每个服务器处理一块,1亿个数分成100块,每个CPU处理一块.然后再从下往上合并.注意:分块的时候,要保证块与块之间独立,没有依赖关系,

TopK问题,腾讯面试题:有100W个战斗力,取前100名的算法。

腾讯面试题:有100W个战斗力,取前100名的算法. 经典topK问题,结论是:随机选择算法 + 快排思想,通过随机选择算法,找到第k大的数,再进行一次快排中的partition,就能得到TopK的结果. 有篇大神的帖子,写的非常好,借鉴下 http://www.sohu.com/a/255145095_178889 原文地址:https://www.cnblogs.com/workharder/p/11980411.html

100万个数中找出最大的前K个数

拿到这个题目我想到了很多方法,但是在我想到的方法中,要把在100万个数中找到前k个数,都不适用.最后通过我的不断研究,我想到了我认为最简单的方法,就是利用堆来做这道题目. 下面我分析一下我用堆排序的思路: 1.我先建一个大小为k的堆. 2.把100万中前k个数放到这个堆中. 3.把这个堆调成小堆. 4.把100万个从k到100万之间的数字拿出来和堆的根结点作比较. 5.如果根结点小于这之间的某一个数,就把这个数拿给根结点,然后继续调成小堆.否则继续找 6.直到找完这100万个数,堆中放的就是最大

Hive中分组取前N个值

分享两篇文章,结合看更清楚一点. 背景 假设有一个学生各门课的成绩的表单,应用hive取出每科成绩前100名的学生成绩. 这个就是典型在分组取Top N的需求. 解决思路 对于取出每科成绩前100名的学生成绩,针对学生成绩表,根据学科,成绩做order by排序,然后对排序后的成绩,执行自定义函数row_number(),必须带一个或者多个列参数,如ROW_NUMBER(col1, ....),它的作用是按指定的列进行分组生成行序列.在ROW_NUMBER(a,b) 时,若两条记录的a,b列相同

如何打造100亿SDK累计覆盖量的大数据系统

作为推送行业领导者,截止目前个推SDK累计安装覆盖量达100亿(含海外),接入应用超过43万,独立终端覆盖超过10亿 (含海外).个推系统每天会产生大量的日志和数据,面临许多数据处理方面的挑战. 首先数据存储方面,个推每天产生10TB以上的数据,并且累积数据已在PB级别.其次,作为推送技术服务商,个推有很多来自客户和公司各部门的数据分析和统计需求,例如:消息推送和数据报表.虽然部分数据分析工作是离线模式,但开源数据处理系统稳定性并不很高,保障数据分析服务的高可用性也是一个挑战.另外,推送业务并不

扛住100亿次请求——如何做一个“有把握”的春晚红包系统?(转载)

转载:原文链接 扛住100亿次请求——如何做一个“有把握”的春晚红包系统? 羊年春晚摇一摇活动已经落下帷幕,现在回过头来看看这一全民参与的有趣的活动背后,有着怎样的后台系统?这个系统又是如何被设计与实现出来的? 1.   春晚摇一摇活动形式 在了解这个系统之前,先看看羊年春晚有哪些活动形式?春晚摇一摇复用了摇一摇入口,但提供了全新的界面和交互内容. 在羊年春晚摇一摇界面里,用户摇动手机后,可以看到明星拜年.全家福.好友贺卡等精彩纷呈的活动页:也会有温馨的“休息一下”,或让很多误以为中奖的“挂服务

面试题-10亿个数中找出最大的10000个数(top K问题)

一个较好的方法:先拿出10000个建立小根堆,对于剩下的元素,如果大于堆顶元素的值,删除堆顶元素,再进行插入操作,否则直接跳过,这样知道所有元素遍历完,堆中的10000个就是最大的10000个.时间复杂度: m + (n-1)logm = O(nlogm) 优化的方法:可以把所有10亿个数据分组存放,比如分别放在1000个文件中(如果是字符串hash(x)%M).对每个文件,建立大小为10000的小根堆,然后按有序数组的合并合并起来,取出最大的10000个即是答案. top K问题 在大规模数据

Oracle 某字段值相同的取前几条数据

rank() over(partition)的使用(转载) 有的时候会遇到这样的问题,我们需要查询一张表,而且要按照业务排序,比如我需要如下的结果: 地区   日期    费用  产品编号   用户编号 290 201202 258 1              s1     290 201202 200 1              s5     290 201202 100 1              s100     290 201202 90   2              s7