从N个数中选取最大的前10个[堆排序版]

题目:

从N个数中选取最大的前10个, 有序输出.

N最大可能达到1000亿

每个数范围是0 - 2147483647


堆排序版测试结果:

总计[1000000]个输入
总计比较[4232804]次
总计写内存[3849024]次
总计耗时[0.046478s]


/* 

 * author: goosman.lei

 * mail: [email protected]

 * blog: http://blog.csdn.net/lgg201

 */


[cpp] view plain copy
  1. #include   
  2. #include   
  3. #include   
  4. #include   
  5. #include   
  6.   
  7. #define BUFF_LEN    (4096)  
  8.   
  9. #define PARENT(i)   ((i) / 2 - 1)  
  10. #define LEFT(i)     ((i + 1) * 2 - 1)  
  11. #define RIGHT(i)    ((i + 1) * 2)  
  12.   
  13. /* #define DEBUG */  
  14. #define INFO  
  15.   
  16. #ifdef INFO  
  17.     int     s_0, s_1, s_2;  
  18.     struct timeval  begin, end;  
  19. #endif  
  20.   
  21. typedef struct queue_s  queue_t;  
  22. struct queue_s {  
  23.     int     data;  
  24.     queue_t *next;  
  25. };  
  26.   
  27. static void generate_test_data(long n) {  
  28.     long    i;  
  29.     int     r;  
  30.     int     l;  
  31.   
  32.     l   = sizeof(int);  
  33.     srand(time(NULL));  
  34.     for ( i = 0; i < n; i ++ ) {  
  35.         r   = rand();  
  36.         fprintf(stdout, "%d\n", r);  
  37.         write(STDERR_FILENO, &r, l);  
  38.     }  
  39. }  
  40. static int read_input(int fd, void *buff, int buff_len) {  
  41.     int     i, ret;  
  42.   
  43.     for ( i = 0; i < buff_len; ) {  
  44.         ret = read(fd, buff, BUFF_LEN);  
  45.         if ( -1 == ret ) {  
  46.             perror("read error\n");  
  47.             exit(0);  
  48.         } else if ( 0 == ret ) {  
  49.             break;  
  50.         } else {  
  51.             buff    += ret;  
  52.             i       += ret;  
  53.         }  
  54.     }  
  55.     return i;  
  56. }  
  57.   
  58. static void dump_link(queue_t *q, int n) {  
  59.     for ( ; q != NULL; q = q->next )  
  60.         fprintf(n ? stderr : stdout, "%d\n", q->data);  
  61.     if ( n ) printf("\n");  
  62. }  
  63.   
  64. void max_heapify(int *sbuff, int j) {  
  65.     int i;  
  66. #ifdef INFO  
  67.     s_0 += 3;  
  68.     s_1 ++;  
  69. #endif  
  70.     if ( sbuff[j] < sbuff[LEFT(j)] )  
  71.         i   = LEFT(j);  
  72.     else  
  73.         i   = j;  
  74.     if ( sbuff[i] < sbuff[RIGHT(j)] ) {  
  75.         i   = RIGHT(j);  
  76. #ifdef INFO  
  77.     s_1 ++;  
  78. #endif  
  79.     }  
  80.     if ( i != j ) {  
  81.         sbuff[i]    ^= sbuff[j];  
  82.         sbuff[j]    ^= sbuff[i];  
  83.         sbuff[i]    ^= sbuff[j];  
  84.         max_heapify(sbuff, i);  
  85. #ifdef INFO  
  86.     s_1 += 3;  
  87. #endif  
  88.     }  
  89. }  
  90. int main(int argc, char *argv[]) {  
  91.     int     *sbuff, *rbuff, *rbuff_t;  
  92.     int     i, j, n, rbuff_n;  
  93.   
  94.     if ( argc < 2 ) {  
  95.         printf("usage: \n\t1. 生成测试数据: %s  /* 标准错误以二进制方式输出测试数据, 标准输出以文本方式输出测试数据用于脚本校验 */\n\t2. 执行Top 10查找: %s  /* 标准输出输出前10个最大数据(倒序), 开启INFO时在标准错误输出统计信息, 开启DEBUG时在标准错误输出调试信息\n",   
  96.             argv[0], argv[0]);  
  97.         return (0);  
  98.     }  
  99.     if ( strcmp(argv[1], "exec") != 0 ) {  
  100.         /* 不考虑数字输入的容错了 */  
  101.         generate_test_data(atoi(argv[1]));  
  102.         return 0;  
  103.     }  
  104.   
  105.     sbuff   = malloc(1024 * 1024 * 4 - 4);  
  106.     rbuff   = malloc(256 * 1024 * 10 * 4);  /* 足够10000亿数据 */  
  107.     rbuff_t = rbuff;  
  108.     rbuff_n = 0;  
  109.   
  110. #ifdef INFO  
  111.     s_0 = 0;  
  112.     s_1 = 0;  
  113.     s_2 = 0;  
  114.     gettimeofday(&begin, NULL);  
  115. #endif  
  116.     while ( 0 != (n = read_input(STDIN_FILENO, sbuff, 1024 * 1024 * 4 - 4)) ) {  
  117. #ifdef INFO  
  118.     s_2 += n / 4;  
  119. #endif  
  120.         for ( j = (n / 4) / 2; j >= 0; j -- ) {  
  121. #ifdef INFO  
  122.     s_0 ++;  
  123. #endif  
  124.             max_heapify(sbuff, j);  
  125.         }  
  126.         for ( i = 0; i < 10; i ++ ) {  
  127. #ifdef INFO  
  128.     s_0 ++;  
  129.     s_1 += 4;  
  130. #endif  
  131.             rbuff[rbuff_n]  = sbuff[0];  
  132.             sbuff[0]        = sbuff[(n / 4) - 1 - i];  
  133.             sbuff[(n / 4) - 1 - i]  = -1;  
  134.             max_heapify(sbuff, 0);  
  135.             rbuff_n ++;  
  136.         }  
  137.     }  
  138.     for ( j = rbuff_n / 2; j >= 0; j -- ) {  
  139. #ifdef INFO  
  140.     s_0 ++;  
  141. #endif  
  142.         max_heapify(rbuff, j);  
  143.     }  
  144.     for ( i = 0; i < 10; i ++ ) {  
  145. #ifdef INFO  
  146.     s_0 ++;  
  147.     s_1 += 4;  
  148. #endif  
  149.         printf("%d\n", rbuff[0]);  
  150.         rbuff[0]    = rbuff[rbuff_n - i];  
  151.         rbuff[rbuff_n - i]  = -1;  
  152.         max_heapify(rbuff, 0);  
  153.     }  
  154. #ifdef INFO  
  155.     gettimeofday(&end, NULL);  
  156. #endif  
  157.   
  158. #ifdef INFO  
  159.     fprintf(stderr, "总计[%d]个输入\n总计比较[%d]次\n总计写内存[%d]次\n总计耗时[%0.6fs]\n",   
  160.         s_2, s_0, s_1, (end.tv_sec * 1000000 + end.tv_usec - begin.tv_sec * 1000000 - begin.tv_usec) / 1000000.0);  
  161. #endif  
  162.   
  163.     return 0;  


你可能感兴趣的:(从N个数中选取最大的前10个[堆排序版])