從海量資料中找中位數(c語言實現)

2021-08-25 20:12:07 字數 3370 閱讀 5777

題目:5億個int,從中找出第k大的數

演算法:之後補上。。。

實現:

#include #include #include #include #include #include #include #include #include typedef struct bucket_t  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)

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].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)

//輸入緩衝區的數已用完

if (bp == length)

length = bytes/4;

bp = 0;

} }//把每個桶剩下的數寫入檔案

for (i = 0; i < nbuckets; 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++)

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)

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);

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)

bytes = write(fd, bucket->buf, bucket->idx*4);

if (bucket->idx*4 != bytes)

close(fd);

}long get_time_usecs()

void swap(int *p, int *q)

/* 把a[t]作為參考,將陣列分成三部分: 小於等於a[t],

* a[t]以及大於a[t],分割完畢後,a[t]所在的下標即是a[t]的順序

*/int partition(int *a, int s, int t)

} swap(a+j, a+t);

return j;

}/* 選擇陣列中第i大的元素並返回 */

int quick_select(int *a, int s, int t, int 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

海量資料找中位數

題目如下 只有2g記憶體的pc機,在乙個存有10g個整數的檔案,從中找到中位數,寫乙個演算法。給出了四種方法來解決 演算法 1.利用外排序的方法,進行排序 然後再去找中位數 2.另外還有個思路利用堆 先求第1g大,然後利用該元素求第2g大,然後利用第2g大,求第3g大.當然這樣的話雖不需排序,但是磁...

從海量資料中找出中位數

題目 在乙個檔案中有 10g 個整數,亂序排列,要求找出中位數。記憶體限制為 2g。只寫出思路即可 記憶體限制為 2g的意思就是,可以使用2g的空間來執行程式,而不考慮這台機器上的其他軟體的占用記憶體 關於中位數 資料排序後,位置在最中間的數值。即將資料分成兩部分,一部分大於該數值,一部分小於該數值...

從海量資料中找出中位數

題目 在乙個檔案中有 10g 個整數,亂序排列,要求找出中位數。記憶體限制為 2g。只寫出思路即可 記憶體限制為 2g的意思就是,可以使用2g的空間來執行程式,而不考慮這台機器上的其他軟體的占用記憶體 關於中位數 資料排序後,位置在最中間的數值。即將資料分成兩部分,一部分大於該數值,一部分小於該數值...