双堆求中位数

求数组中位数的方法:

1、排序

2、双堆

3、findk

效率分别是nlog(n)、nlog(n)、log(n)

用堆维护中位数的意思是说,设计两个堆,第一个堆存放小于中位数的元素,第二个堆存放大于中位数的元素。

下面是双堆维护中位数的语言描述:

1、初始化的时候设置两个变量分别记录两个堆【左堆和右堆】的元素的个数

2、取第一个元素【d[0]】作为初始中位数m

3、循环后面的每一个元素,如果比m大,则插入到右堆,如果比m小,则插入到左堆

4、此时如果左堆和右堆的元素数目之差的绝对值等于2,说明左右两侧的元素不平衡了。需要把m插入到元素少的那个数组中,然后取下一个数组元素作为中位数,重复3和4。

5、经过上述步骤,数组的所有元素都已经在堆中了。如果两个堆的数据元素个数相等那么有两个中位数,即两个堆的堆顶。如果两个堆的数据数目不相等,则元素多的那个堆的堆顶是数组中位数。

### 中位数的定义与解方法 中位数是指一组有序数据中间位置上的数值。如果数据的数量为奇数,则中位数是位于中间的那个数;如果是偶数,则中位数是中间两个数的平均值。 #### 使用堆结构实现动态中位数计算 为了高效地维护并查询中位数,可以采用双堆(最大堆和最小堆)的方式[^2]: - **最大堆**:存储较小的一半数据,其根节点始终保存这一部分的最大值。 - **最小堆**:存储较大的一半数据,其根节点始终保存这一部分的最小值。 通过这种方式,可以在 $O(\log n)$ 的时间内完成插入操作,并在常数时间 $O(1)$ 获取当前的中位数。 以下是基于 C++ 实现的一个例子: ```cpp #include <iostream> #include <queue> using namespace std; class MedianFinder { public: priority_queue<int> maxHeap; // 大顶堆,存小的那一半数 priority_queue<int, vector<int>, greater<int>> minHeap; // 小顶堆,存大的那一半数 /** 添加一个数字 */ void addNum(int num) { if (maxHeap.empty() || num <= maxHeap.top()) { maxHeap.push(num); } else { minHeap.push(num); } // 调整两堆大小平衡 if (maxHeap.size() > minHeap.size() + 1) { minHeap.push(maxHeap.top()); maxHeap.pop(); } else if (minHeap.size() > maxHeap.size()) { maxHeap.push(minHeap.top()); minHeap.pop(); } } /** 查找中位数 */ double findMedian() { if (maxHeap.size() == minHeap.size()) { return (maxHeap.top() + minHeap.top()) / 2.0; } else { return maxHeap.top(); // 奇数情况下返回大顶堆的顶部元素 } } }; int main() { MedianFinder mf; int nums[] = {1, 3, 5, 7, 9}; for(auto& num : nums){ mf.addNum(num); cout << "Current median is: " << mf.findMedian() << endl; } } ``` 上述代码实现了 `addNum` 和 `findMedian` 方法来分别处理新增加的数据以及获取当前的中位数。这种方法适用于实时更新场景下的中位数查找问题。 对于静态数组的情况,可以通过先对数组排序再选取相应位置的值作为中位数。例如,在已知长度的情况下可以直接定位到中心点或者取均值[^1]。 ### 静态数组中的中位数计算实例 下面是一个简单的C语言程序用于演示如何在一个固定大小的数组上找到其中位数: ```c #include <stdio.h> #include <stdlib.h> void sortArray(int *arr, int size) { qsort(arr, size, sizeof(int), (int(*)(const void*, const void*))strcmp); } double getMedian(int sortedArr[], int length) { if(length % 2 != 0) return (double)sortedArr[length/2]; else return ((double)(sortedArr[(length-1)/2]+sortedArr[length/2])/2.0; } int main(){ int data[5]={4,8,6,2,10}; int len=sizeof(data)/sizeof(data[0]); sortArray(data,len); printf("The median value is %.2lf\n",getMedian(data,len)); return 0; } ``` 此段代码首先利用标准库函数qsort对输入数组进行了升序排列,之后依据数组长度判断是否需要计算单个还是多个元素构成的中位数
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值