- 浏览: 723817 次
- 性别:
- 来自: 北京
最新评论
-
wxweven:
Surmounting 写道既然 Java 的跳表那么少,我决 ...
SkipList 跳表 -
暮雪云然:
写的不错,很透彻
Java静态内部类 -
bzhao:
好,赞扬!
Linux信号详解 -
jacktao219:
赞一个~! ,现在正在看redis 所以接触到跳表
SkipList 跳表 -
is_leon:
vote--后还要判断是否为0吧,如果为0则废掉重新置位can ...
现在有一个整数数组,已知一个数出现的次数超过了一半,请用O(n)的复杂度的算法找出这个数
题目:5亿个int,从中找出第k大的数
算法:之后补上。。。
实现:
#include <assert.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/time.h> #include <sys/types.h> #include <sys/stat.h> typedef struct bucket_t { int *buf; /* 输出缓冲区 */ int count; /* 当前有多少个数 */ int idx; /* 缓冲区的指针 */ } bucket_t; static unsigned int BUF_PAGES; /* 缓冲区有多少个page */ static unsigned int PAGE_SIZE; /* page的大小 */ static unsigned int BUF_SIZE; /* 缓冲区的大小, BUF_SIZE = BUF_PAGES*PAGE_SIZE */ static unsigned int nbuckets; /* 分成多少个桶 */ static unsigned int BUCKET_BUF_SIZE; static int *buffer; /* 输入缓冲区 */ long get_time_usecs(); void write_to_file(bucket_t *bucket, int pos); int partition(int *a, int s, int t); int quick_select(int *a, int s, int t, int i); void swap(int *p, int *q); int main(int argc, char **argv) { char filename[20]; unsigned int bp, length, bucket_size, k; int fd, i, bytes; bucket_t *bucket; long start_usecs = get_time_usecs(); strcpy(filename, argv[1]); fd = open(filename, O_RDONLY); if (fd < 0) { printf("can't open file %s\n", filename); exit(0); } nbuckets = 1024; k = atoi(argv[2]); PAGE_SIZE = 4096; /* page = 4KB */ BUF_PAGES = 1024; BUF_SIZE = PAGE_SIZE*BUF_PAGES; /* 4KB * 1024 = 4M */ BUCKET_BUF_SIZE = PAGE_SIZE*128; /* 4KB * 128 = 512KB */ buffer = (int *)malloc(BUF_SIZE); //把1-2^32个数分成nbucket个组, nbuckets必须等于2的n次幂 bucket = malloc(sizeof(bucket_t)*nbuckets); if (bucket == NULL) exit(0); for (i = 0; i < nbuckets; i++) { bucket[i].buf = malloc(BUCKET_BUF_SIZE); if (bucket[i].buf == NULL) { exit(0); } bucket[i].idx = 0; bucket[i].count = 0; } bucket_size = (1<<22); /* 分成1024个桶,每个桶容纳2^22个数 */ // 读入第一批数据到输入缓冲区 bytes = read(fd, buffer, BUF_SIZE); length = bytes/4; bp = 0; int element, pos; unsigned int base; bucket_t *p; base = 2147483648; while (1) { //从输入缓冲区取出一个数,加到对应的桶 element = buffer[bp++]; pos = (((long)element)+base)>>22; p = &bucket[pos]; p->buf[p->idx++] = element; p->count++; //桶内的缓冲区已满,写入文件 if (p->idx*4 == BUCKET_BUF_SIZE) { write_to_file(p, pos); p->idx = 0; } //输入缓冲区的数已用完 if (bp == length) { bytes = read(fd, buffer, BUF_SIZE); if (bytes == 0) { break; } length = bytes/4; bp = 0; } } //把每个桶剩下的数写入文件 for (i = 0; i < nbuckets; i++) { write_to_file(bucket+i, i); } free(buffer); close(fd); buffer = malloc(bucket_size*4); if (buffer == NULL) exit(0); //找出第k大的数位于哪个文件 unsigned sum = 0; for (i = 0; i < nbuckets && sum < k; i++) { sum += bucket[i].count; } i--; //把该文件读入内存 sprintf(filename, "foo_%d.dat", i); printf("第%d大的数位于文件%s的第%d大的数\n", k, filename, k+bucket[i].count-sum); fd = open(filename, O_RDONLY); if (fd < 0) { printf("can't open file %s\n", filename); free(buffer); exit(0); } bytes = read(fd, buffer, bucket_size*4); length = bytes/4; //选择文件内第(k+bucket[i].count-sum)大的数 int answer; answer = quick_select(buffer, 1, length-1, k+bucket[i].count-sum); printf("第%d大的数 = %d\n", k, answer); close(fd); free(buffer); //free buckets for (i = 0; i < nbuckets; i++) { free(bucket[i].buf); } free(bucket); long end_usecs = get_time_usecs(); double secs = (double)(end_usecs - start_usecs) / (double)1000000; printf("it took %.02f seconds.\n", secs); return 0; } void write_to_file(bucket_t *bucket, int pos) { char filename[20]; int fd, bytes; sprintf(filename, "foo_%d.dat", pos); fd = open(filename, O_WRONLY | O_CREAT | O_APPEND, 0666); if (fd < 0) { printf("can't open file %s\n", filename); exit(0); } bytes = write(fd, bucket->buf, bucket->idx*4); if (bucket->idx*4 != bytes) { printf("idx = %d, bytes = %d, write error\n", bucket->idx, bytes); close(fd); exit(0); } close(fd); } 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; } void swap(int *p, int *q) { int tmp; tmp = *p; *p = *q; *q = tmp; } /* 把a[t]作为参考,将数组分成三部分: 小于等于a[t], * a[t]以及大于a[t],分割完毕后,a[t]所在的下标即是a[t]的顺序 */ int partition(int *a, int s, int t) { int i, j; /* i用来遍历a[s]...a[t-1], j指向大于x部分的第一个元素 */ for (i = j = s; i < t; i++) { if (a[i] < a[t]) { swap(a+i, a+j); j++; } } swap(a+j, a+t); return j; } /* 选择数组中第i大的元素并返回 */ int quick_select(int *a, int s, int t, int i) { int p, m; if (s == t) return a[t]; p = partition(a, s, t); m = p - s + 1; if (m == i) return a[p]; if (m > i) { return quick_select(a, s, p-1, i); } return quick_select(a, p+1, t, i-m); }
运行和测试:
寻找第1111大的整数
dd if=/dev/urandom of=random.dat bs=1M count=1024
gcc main.c
./a.out random.dat 1111
发表评论
-
Paxos算法
2012-04-18 10:59 2659分布式系统的核心问题是数据一致性,解决一致性有很多算法,而 P ... -
编程之美3.3 计算字符串的相似度
2012-03-13 23:26 33问题描述 定义一套操作方法, 把两个不相同的字符串变得相同, ... -
编程之美3.1 字符串移位包含的问题
2012-03-12 23:26 3326题目 给定两个字符串 s ... -
SkipList 跳表
2011-10-09 01:08 39761为什么选择跳表 目前经常使用的平衡数据结构有:B树,红黑树, ... -
(转)一致性哈希算法及其在分布式系统中的应用
2011-09-29 19:02 2316原文地址: http://www.cnb ... -
算法导论习题 5.1 -2
2011-09-29 09:23 2001描述random(a, b)过程的一种实现,它只调用rando ... -
现在有一个整数数组,已知一个数出现的次数超过了一半,请用O(n)的复杂度的算法找出这个数
2011-05-05 19:43 6234现在有一个整数数组,已知一个数出现的次数超过了一半,请用O(n ... -
寻找最大的K个数 (C语言实现)
2011-05-04 16:31 5343题目:100亿个整数,求最大的1万个数,并说出算法的时间复杂度 ... -
kmp算法的理解与实现
2011-04-30 21:29 25494KMP算法曾被我戏称为看毛片算法,当时笑喷...... ... -
败者树 多路平衡归并外部排序
2011-04-25 21:52 10677一 外部排序的基本思路 ... -
实现两个整数的除法,不能用除号和乘号
2011-04-22 15:17 3635对于两个整数a和b, 求a/b,可以从1开始枚举结果resul ... -
最大公共子字符串(Longest Common Substring)
2011-04-22 13:33 3407Longest Common Substring和Longes ... -
poj 1458 最长公共子串(Longest Common Subsequence)
2011-04-22 10:45 2567LCS问题: 给定序列 X = <x1,x2,... ... -
归并排序
2011-04-21 21:51 1170#include <stdio.h> #i ... -
快速排序 顺序统计量 数组分割
2011-04-21 19:28 1362#include <stdio.h> #in ... -
位运算集锦
2011-04-21 17:15 2108文中2'k代表2的k次方 1 除以2的k次幂可以用位运 ... -
最长递增子序列
2011-04-21 14:45 1184设L = <a1,a2,...an>是n个不同的实 ... -
poj 2774 后缀数组
2011-03-21 17:28 1784#include <stdio.h> # ... -
poj 2823 线段树
2011-03-17 18:49 1618赤裸裸的线段树,数据量很大,加了IO优化函数。 #in ... -
poj 3368 RMQ 线段树 离散化
2011-03-17 17:00 2733一 题意:给定递增序列 ...
相关推荐
此外,系统可能还包含了数据挖掘和机器学习算法的实现,如聚类、分类、预测模型等,这些算法可以自动从海量数据中发现有价值的模式,实现智能预测和决策支持。 在实际应用中,这个C语言实现的工业数据分析系统可以...
在有内存限制的情况下找出10G个整数中的中位数问题,可以考虑使用“中位数的中位数”算法,该算法可以将复杂度降低到O(N)。 时分秒针在一天之内重合的次数,可以通过分析它们的运动规律计算得出。 将多个集合合并...
- **薪酬水平分布**:根据不同职位和地区,统计薪酬的平均值、中位数等指标。 - **工作经验要求**:探索不同职位对应的工作经验要求。 - **技能要求分析**:通过文本挖掘技术分析职位描述中提到的技能关键词。 **...
随着大数据和云计算的兴起,大数运算变得至关重要,因为它允许我们处理海量的数据和进行复杂的数学运算。本文将介绍如何使用C语言实现大数的加法和减法运算。 首先,大数是以字符串的形式存储的,每个字符代表一个...
- **挑战与难点**:由于地形结构的复杂性以及海量数据的存在,实现实时且具有真实感的大范围三维地形显示面临着巨大挑战。主要难点在于如何高效管理和简化地形数据,以确保快速准确的可视化。 #### 二、openGL在...
- 数据中心是由成千上万个处理器组成的大型集群,用于存储、管理和处理海量数据。这些数据中心是互联网服务的基础。 **1.1.8 多核处理器** - 多核处理器是指在一个芯片上集成多个独立的处理器核心。这种方式可以...
计算机科学导论试卷主要涵盖了计算机基础知识,包括计算机组成、数据表示、编程语言、操作系统、数据库、网络和信息安全等多个方面。...28. **IPv6地址长度**:IPv6地址由128位二进制数组成,提供海量的IP地址空间。
在分析过程中,可能涉及到的操作有排序、查找、统计计算(平均值、中位数、方差等)、数据可视化以及机器学习模型的训练等。 为了高效地处理大数据,程序员可能会使用并行计算、分布式计算框架,如Apache Hadoop或...
- **知识点**:C语言标准库函数实现原理。 - **应用场景**:操作系统开发、嵌入式系统编程等。 - **第五章:寻找满足条件的两个或多个数** - **知识点**:哈希表、双指针技术。 - **应用场景**:算法竞赛、在线...
#### 四、海量数据处理技巧 - **题目解析**:这部分涉及大规模数据处理的方法。 - **统计不同整数数量**:可以使用位图(Bit Map)来高效统计不同整数的数量。假设待处理的整数范围为`0`到`2.5亿-1`,可以创建一个...
- **大数据处理**:对海量交通数据进行收集、存储、处理和分析。 - **数据库系统**:用于组织、存储和管理数据的软件系统。 - **SQL语言**:用于查询、更新数据库的标准语言。 综上所述,本大纲覆盖了从硬件底层的...
演讲者从多个角度阐述了为何选择Golang作为主要编程语言,并介绍了其在实际应用中的具体实现方法。 #### 二、RTB与DSP概念详解 - **RTB(Real-time Bidding)**:实时竞价是一种广告交易方式,允许广告买家根据特定...
- **定义**:位是计算机中最小的信息单位,表示二进制数中的0或1。 - **作用**:构成计算机中的所有数据和指令的基础。 - **单位换算**:8个位组成一个字节(Byte)。 #### 18. 系统软件(System Software) - **定义**...