`
kenby
  • 浏览: 726457 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

从海量数据中找中位数(c语言实现)

阅读更多

题目: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

 

 

分享到:
评论

相关推荐

    c语言如何对海量数据进行处理

    但受限于C语言不自带高级数据处理库,以及常见的内存和计算资源限制,针对海量数据的处理必须采用特定的策略和算法。本文将针对几个具体的海量数据处理场景,探讨如何使用C语言以及一些高效算法来应对这些挑战。 ##...

    c语言实现的工业数据分析系统

    此外,系统可能还包含了数据挖掘和机器学习算法的实现,如聚类、分类、预测模型等,这些算法可以自动从海量数据中发现有价值的模式,实现智能预测和决策支持。 在实际应用中,这个C语言实现的工业数据分析系统可以...

    2021年威海地区C语言工程师岗位薪酬水平报告-最新数据.pdf

    例如,P50的中位数指标可以帮助读者了解一半的C语言工程师的薪酬水平,而P90则能让企业或个人了解到在该行业中,只有10%的工程师能够达到或超过的薪酬标准。 此外,报告还梳理了全国各地区的常用岗位薪酬水平。通过...

    大厂面试系列二.pdf

    在有内存限制的情况下找出10G个整数中的中位数问题,可以考虑使用“中位数的中位数”算法,该算法可以将复杂度降低到O(N)。 时分秒针在一天之内重合的次数,可以通过分析它们的运动规律计算得出。 将多个集合合并...

    网络招聘数据可视化分析计算机系统的设计与实现.docx

    - **薪酬水平分布**:根据不同职位和地区,统计薪酬的平均值、中位数等指标。 - **工作经验要求**:探索不同职位对应的工作经验要求。 - **技能要求分析**:通过文本挖掘技术分析职位描述中提到的技能关键词。 **...

    大数运算数据结构

    随着大数据和云计算的兴起,大数运算变得至关重要,因为它允许我们处理海量的数据和进行复杂的数学运算。本文将介绍如何使用C语言实现大数的加法和减法运算。 首先,大数是以字符串的形式存储的,每个字符代表一个...

    基于openGL的三维地形场景的生成

    - **挑战与难点**:由于地形结构的复杂性以及海量数据的存在,实现实时且具有真实感的大范围三维地形显示面临着巨大挑战。主要难点在于如何高效管理和简化地形数据,以确保快速准确的可视化。 #### 二、openGL在...

    tkyte_exadata2.ppt

    Exadata系统结合了硬件和软件的创新,包括数据库机器学习、智能存储以及高速网络技术,旨在处理海量数据和复杂查询时保持出色性能。 自动存储管理(Automatic Storage Management, ASM)是Oracle数据库中的一个重要...

    Computer Organization and Design, 4th Ed, D. A. Patterson and J. L. Hennessy Chapter 1

    - 数据中心是由成千上万个处理器组成的大型集群,用于存储、管理和处理海量数据。这些数据中心是互联网服务的基础。 **1.1.8 多核处理器** - 多核处理器是指在一个芯片上集成多个独立的处理器核心。这种方式可以...

    计算机导论试卷8.pdf

    计算机科学导论试卷主要涵盖了计算机基础知识,包括计算机组成、数据表示、编程语言、操作系统、数据库、网络和信息安全等多个方面。...28. **IPv6地址长度**:IPv6地址由128位二进制数组成,提供海量的IP地址空间。

    ideltifier.rar_大数据_Others_

    在分析过程中,可能涉及到的操作有排序、查找、统计计算(平均值、中位数、方差等)、数据可视化以及机器学习模型的训练等。 为了高效地处理大数据,程序员可能会使用并行计算、分布式计算框架,如Apache Hadoop或...

    程序员编程艺术第一~二十七章集锦与总结(教你如何编程)

    - **知识点**:C语言标准库函数实现原理。 - **应用场景**:操作系统开发、嵌入式系统编程等。 - **第五章:寻找满足条件的两个或多个数** - **知识点**:哈希表、双指针技术。 - **应用场景**:算法竞赛、在线...

    计算机组成原理与汇编语言程序设计课后习题及解答

    - **强大的存储能力**:能够存储海量的数据和程序。 - **高度通用性**:适用于多个领域,如科学计算、数据处理、图形渲染等。 #### 5. 计算机性能评估指标 计算机性能通常通过以下指标进行评估: - **基本字长**:...

    百度技术类笔试题目最全合集

    #### 四、海量数据处理技巧 - **题目解析**:这部分涉及大规模数据处理的方法。 - **统计不同整数数量**:可以使用位图(Bit Map)来高效统计不同整数的数量。假设待处理的整数范围为`0`到`2.5亿-1`,可以创建一个...

    历年百度笔试题精华集锦

    5. **结构体大小计算**:在C语言中,结构体的大小是其成员大小的总和,加上必要的对齐填充。对于这个问题,需要考虑指针、字符、短整型、位字段和结构体指针的大小,以及内存对齐规则。 6. **排序算法比较次数**:...

    北京航空航天大学831交通信息综合2021年考研专业课初试大纲.pdf

    - **大数据处理**:对海量交通数据进行收集、存储、处理和分析。 - **数据库系统**:用于组织、存储和管理数据的软件系统。 - **SQL语言**:用于查询、更新数据库的标准语言。 综上所述,本大纲覆盖了从硬件底层的...

    【Gopher China 2015】Golang与高性能DSP竞价系统

    演讲者从多个角度阐述了为何选择Golang作为主要编程语言,并介绍了其在实际应用中的具体实现方法。 #### 二、RTB与DSP概念详解 - **RTB(Real-time Bidding)**:实时竞价是一种广告交易方式,允许广告买家根据特定...

Global site tag (gtag.js) - Google Analytics