堆
堆的动态创建与删除可参考 http://www.java3z.com/cwbwebhome/article/article1/1362.html?id=4745,此处不再赘述。
双堆求中位数
算法描述:
1、创建两个堆(一个小根堆、一个大根堆),堆大小至少为给定数据个数的一半,向上取整;
2、假定变量mid用来保存中位数,取定第一个元素,赋值给mid,即作为初始的中位数;
3、依次遍历后面的每一个数据,如果比mid小,则插入大根堆;否则插入小根堆;
4、如果大根堆和小根堆上的数据个数相差为2,则将mid插入到元素个数较少的堆中,然后从元素个数较多的堆中删除根节点,并将跟节点赋值给mid;
5、重复步骤3和4,直到所有的数据遍历结束;
此时,mid保存了一个数,再加上两个堆中保存的数,就构成了给定数据的集合。
如果两个堆中元素个数相等,则mid即为最终的中位数;否则,元素较多的堆的根节点元素与mid的和求平均值,即为最终的中位数。
算法实现
算法实现采用了整数,所以,最终的结果取了整数,可以将返回值转换为浮点型,更精确。
uint32_t getmiddle(uint32_t *array, uint32_t size) { int i = 0, minelem = 0, maxelem = 0; uint32_t mid = array[0]; uint32_t heapsize = (size+1)/2; heap_t *minheap = heap_malloc(heapsize); heap_t *maxheap = heap_malloc(heapsize); for(i = 1; i < size; i++) { if(array[i] < mid) { maxheap_insert(maxheap, array[i]); maxelem++; } else { minheap_insert(minheap, array[i]); minelem++; } if(minelem - maxelem > 1) { maxheap_insert(maxheap, mid); mid = minheap->element[0]; minheap_delete(minheap); maxelem++; minelem--; } if(maxelem - minelem > 1) { minheap_insert(minheap, mid); mid = maxheap->element[0]; maxheap_delete(maxheap); minelem++; maxelem--; } } printf("\nmaxelem = %d, minelem = %d, pre_mid = %d\n", maxelem, minelem,mid); if(minelem > maxelem) { printf("\nmid[ %d ] = ( mid [ %d ]+minheap->element[0][ %d ] )/2 = %d\n",mid, mid, minheap->element[0],(mid+minheap->element[0])/2); mid = (mid+minheap->element[0])/2; } if(maxelem < maxelem) { printf("\nmid[ %d ] = ( mid [ %d ]+maxheap->element[0][ %d ] )/2 = %d\n",mid, mid, minheap->element[0],(mid+maxheap->element[0])/2); mid = (mid+maxheap->element[0])/2; } heap_free(minheap); heap_free(maxheap); return mid; }
测试程序
int main(int argc, char *argv[]) { int num = 10; uint32_t array[num] = {2,20,13,18,15,8,3,5,4,25}; getmiddle(array, num); printf("\n"); return 0; }
测试结果
时间: 2024-10-08 03:07:51