/** * 100w 个整数里取出最大的 500 个: * 可以转换为 n 个数里取出最大的 m 个,其中 m < n,采用堆排序实现,时间复杂度为 n + nlogm * 举例:12 20 9 18 7 14 几个数中取出最大的三个: * 做法:遍历所需计算的整数。创建一个节点数为3的最小堆,当堆装满后,再来的数与根节点对比,如果比根节点大,替换,然后再走到根节点相应的位置,图例如下: * (0) (1) (2) (3) (4) (5) (6) (7) (8) * 12 12 12 12 9 18 12 7 丢弃 14 * / / \ / \ / \ / \ / \ / * 20 20 9 9 20 12 20 12 20 18 20 18 20 * 希望读者有更好方法的不吝赐教 */ #include<stdio.h> #define LENGTH(s) (sizeof(s) / sizeof(s[0])) //取数组长度 define 不是定义数组,而是把一段代码取一个别名 /** * 交换两个整数 */ void swap(int *a, int *b){ *a = *a ^ *b; *b = *a ^ *b; *a = *a ^ *b; } /** * 将节点与其子节点对比,如果比子节点大,则与其交换,替换完了再保证被替换的同节点比右边的弟兄节点小,否则左右兄弟节点交换 */ int shift_down(int *r, int i){ if( i >= LENGTH(r) ) return i; int left, right, last_left; left = 2 * i +1; // 如果节点比左了节点大,交换,如注释中第(6)步 if( r[i] > r[left] ){ swap(&r[i], &r[left]); last_left = shift_down(r, left); // 如果右节点存在,左右对比,保证左节点比右节点小,如注释中第(3)步 if( last_left <= sizeof(r) - 2 ){ if(r[last_left] > r[last_left+1]) swap(&r[last_left], &r[last_left+1]); } return 0; }else{ return i; } } /** * 判断节点是否为右节点 */ int is_right(int i){ return (i > 0) && ( (i -1) % 2 == 1); } /** * 将节点与父节点对比,如果比爷节点大,则民其交换,替换完再保证左节点始终比右节点小 */ int shift_up(int *r, int i){ if( i <= 0 ) return i; int parent; parent = (i -1) / 2; if(r[parent] > r[i]){ swap(&r[parent], &r[i]); shift_up(r, parent); } return 0; } int main(){ int r_size = 3; // 取出结果数 int arr[8] = {12, 20, 9, 18, 7, 14, 21, 28}; //待处理数组 int r[r_size]; int arr_size, i = 0, result_size = 0; arr_size = LENGTH(arr); for( i = 0; i < arr_size; i++ ){ //判断结果堆是否满,未满直接加上,若满与第一个对比 if( result_size >= r_size ){ if( arr[i] > r[0] ){ //替换根节点,如注释中第(5)步 r[0] = arr[i]; // 调整位置,将最小位置到根节点,如注释中第(6)步 shift_down(r, 0); } }else{ // 如果根节点还没填满,在节点末插入一个新节点 r[result_size] = arr[i]; // 如果是右节点,与左节点对比,如果比左节点小,左右交换 if( is_right(result_size) && r[result_size] < r[result_size-1] ) swap(&r[result_size], &r[result_size-1]); shift_up(r, result_size); result_size ++; } } for(i = 0; i < r_size; i++){ printf("\n %d: %d", i, r[i]); } return 0; }
100w 个整数里取出最大的 500 个, 可以转换为 n 个数里取出最大的 m 个
原文地址:http://blog.csdn.net/agangdi/article/details/41382147