題目: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的空間來執行程式,而不考慮這台機器上的其他軟體的占用記憶體 關於中位數 資料排序後,位置在最中間的數值。即將資料分成兩部分,一部分大於該數值,一部分小於該數值...