- 浏览: 716819 次
- 性别:
- 来自: 北京
最新评论
-
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 2481分布式系统的核心问题是数据一致性,解决一致性有很多算法,而 P ... -
编程之美3.3 计算字符串的相似度
2012-03-13 23:26 33问题描述 定义一套操作方法, 把两个不相同的字符串变得相同, ... -
编程之美3.1 字符串移位包含的问题
2012-03-12 23:26 3258题目 给定两个字符串 s ... -
SkipList 跳表
2011-10-09 01:08 39243为什么选择跳表 目前经常使用的平衡数据结构有:B树,红黑树, ... -
(转)一致性哈希算法及其在分布式系统中的应用
2011-09-29 19:02 2269原文地址: http://www.cnb ... -
算法导论习题 5.1 -2
2011-09-29 09:23 1957描述random(a, b)过程的一种实现,它只调用rando ... -
现在有一个整数数组,已知一个数出现的次数超过了一半,请用O(n)的复杂度的算法找出这个数
2011-05-05 19:43 6162现在有一个整数数组,已知一个数出现的次数超过了一半,请用O(n ... -
寻找最大的K个数 (C语言实现)
2011-05-04 16:31 5287题目:100亿个整数,求最大的1万个数,并说出算法的时间复杂度 ... -
kmp算法的理解与实现
2011-04-30 21:29 25411KMP算法曾被我戏称为看毛片算法,当时笑喷...... ... -
败者树 多路平衡归并外部排序
2011-04-25 21:52 10505一 外部排序的基本思路 ... -
实现两个整数的除法,不能用除号和乘号
2011-04-22 15:17 3591对于两个整数a和b, 求a/b,可以从1开始枚举结果resul ... -
最大公共子字符串(Longest Common Substring)
2011-04-22 13:33 3338Longest Common Substring和Longes ... -
poj 1458 最长公共子串(Longest Common Subsequence)
2011-04-22 10:45 2516LCS问题: 给定序列 X = <x1,x2,... ... -
归并排序
2011-04-21 21:51 1134#include <stdio.h> #i ... -
快速排序 顺序统计量 数组分割
2011-04-21 19:28 1327#include <stdio.h> #in ... -
位运算集锦
2011-04-21 17:15 2041文中2'k代表2的k次方 1 除以2的k次幂可以用位运 ... -
最长递增子序列
2011-04-21 14:45 1153设L = <a1,a2,...an>是n个不同的实 ... -
poj 2774 后缀数组
2011-03-21 17:28 1740#include <stdio.h> # ... -
poj 2823 线段树
2011-03-17 18:49 1568赤裸裸的线段树,数据量很大,加了IO优化函数。 #in ... -
poj 3368 RMQ 线段树 离散化
2011-03-17 17:00 2686一 题意:给定递增序列 ...
相关推荐
c语言回文数回文数c语言实现回文数c语言实现回文数c语言实现回文数c语言实现回文数c语言实现回文数c语言实现c语言回文数回文数c语言实现回文数c语言实现回文数c语言实现回文数c语言实现回文数c语言实现回文数c语言...
DMA传输的C语言实现DMA传输的C语言实现DMA传输的C语言实现DMA传输的C语言实现DMA传输的C语言实现DMA传输的C语言实现DMA传输的C语言实现DMA传输的C语言实现DMA传输的C语言实现DMA传输的C语言实现DMA传输的C语言实现...
清华严蔚敏《数据结构》的全部代码实现C语言
KNN算法实现鸢尾花数据集分类 C语言实现 KNN算法实现鸢尾花数据集分类 C语言实现 KNN算法实现鸢尾花数据集分类 C语言实现 KNN算法实现鸢尾花数据集分类 C语言实现 KNN算法实现鸢尾花数据集分类 C语言实现 KNN...
数据结构中十字链表的C语言实现 数据结构中十字链表的C语言实现
一个课程用的小程序,排序实现查找数组中的中位数
文档为数据结构课程相关章节的算法实现,每一部分的代码都可以单独运行,不止是单个函数,C语言版,与《数据结构(C语言版)》严蔚敏配套使用。面向学习计算机专业数据结构的同学,期末考试,做ACM的同学;计算机专业...
用c语言实现的线性表,很好的理解数据结构中的线性表的结构和用法
数据结构 图操作 图研究 图C语言实现 完整的代码 本人学习的时候写的 感觉很好 希望能给你们带来启发
数据结构中矩阵的C语言实现 数据结构中矩阵的C语言实现
C语言实现从文件中读取数据。 一篇文章带你快速了解!
基于Linux使用C语言实现的一个串口通讯Demo,实测可用。
自己用c语言来实现数据结构中的栈,详细的介绍了栈的结构
c语言实现杨辉三角 数据结构资源 c语言实现杨辉三角 数据结构资源 c语言实现杨辉三角 数据结构资源
用C语言编写数据结构代码。C语言实现数据结构的代码,像单链表,栈,队列,二叉树,图等数据结构,用c来实现
循环链表数据结构C语言实现
c语言实现数据结构折半查找
用c语言实现图形树,可以清楚的了解二叉树的结构
C语言实现求不同数字的个数C语言实现求不同数字的个数
C语言中float类型的实现! C语言中float类型的实现! C语言中float类型的实现! C语言中float类型的实现! C语言中float类型的实现! C语言中float类型的实现! C语言中float类型的实现! C语言中float类型的实现! ...