首页 > C++的 STL堆 实现获取中位数

C++的 STL堆 实现获取中位数

前言

堆数据结构 使用的是优先级队列实现,创建堆的时候需要指定堆中元素的排列方式,即最大堆或者最小堆

最大堆即 堆顶元素为堆中最大的元素

最小堆即 堆顶元素为堆中最小堆元素

如下为一个最大堆

在这里插入图片描述

中位数:

一组数排序后,如果元素个数如下

奇数个数n:(int) n/2 的数

偶数个数n: (int) n/2 和(int) n/2 +1的平均数


同样此时想要获取一组数列中的中位数,且同样使用时间复杂度为O(n)进行解决,这个时候使用堆的数据结构是最为有效的

解决办法如下:

动态维护一个最大堆与一个最小堆,最大堆存储一半数据,最小堆存储 一般数据,维持最大堆的堆顶比最小堆的堆顶小。

在这里插入图片描述

在维护这两个堆的过程中核心为

  1. 最大堆的堆顶元素需要小于堆小堆的堆顶元素
  2. 两个堆元素个数相差不能超过1

保证核心的情况下需要考虑如下三种情况:

a. 最大堆的元素和最小堆的元素个数相等

此时入堆需要根据进入元素和两个堆顶元素大小比较的结果从而选择入哪个堆

b. 最大堆的元素个数大于最小堆的元素个数

此时入堆需要分两种情况:进入元素的大小小于最大堆的堆顶,进入元素大小大于最大堆的堆顶

c. 最大堆的元素个数小于最小堆的元素个数

此时入堆需要分两种情况:进入元素的大小大于最小堆的堆顶,进入元素大小小于最小堆的堆顶

实现过程如下(文末有完整测试代码):

/*
核心:
1. 保证最大堆的堆顶小于最小堆的堆顶,这样就保证了最大堆的元素都小于最小堆的元素
2. 两个堆中堆元素个数相差不能超过1
*/
void GetMedian::push(int num) { /*初始化一个最大堆即可*/if(big_heap.empty()){ big_heap.push(num);return;}/*第一种情况,两个堆的大小相等*/if(big_heap.size() == small_heap.size()) { if (num <= big_heap.top()) {  //元素小于最大堆堆堆顶,则入最大堆big_heap.push(num);} else {  //否push最小堆small_heap.push(num);}} else if(big_heap.size() > small_heap.size()) { //第二种情况/*此时入堆元素小于最大堆的堆顶,按照第一个核心,需要入最大堆但是为了保证两个堆大小个数相差不能超过1则需要将最大堆堆堆顶取出来放入最小堆,再将当前元素入堆*/if (num <= big_heap.top()) {  small_heap.push(big_heap.top());big_heap.pop();big_heap.push(num);} else {  // 否则直接入最小堆small_heap.push(num);}} else {  //第三种情况处理刚好和以上步骤相反if (num >= small_heap.top()) { big_heap.push(small_heap.top());small_heap.pop();small_heap.push(num);} else { big_heap.push(num);}}
}

完整测试代码如下:

#include 
#include using namespace std;class GetMedian{ private:priority_queue<int,vector<int>,greater<int>> small_heap;priority_queue<int,vector<int>,less<int>> big_heap;public:GetMedian(){ };void push(int num);double getMedia(); 
};void GetMedian::push(int num) { if(big_heap.empty()){ big_heap.push(num);return;}if(big_heap.size() == small_heap.size()) { if (num <= big_heap.top()) { big_heap.push(num);} else { small_heap.push(num);}} else if(big_heap.size() > small_heap.size()) { if (num <= big_heap.top()) { small_heap.push(big_heap.top());big_heap.pop();big_heap.push(num);} else { small_heap.push(num);}} else { if (num >= small_heap.top()) { big_heap.push(small_heap.top());small_heap.pop();small_heap.push(num);} else { big_heap.push(num);}}
}double GetMedian::getMedia() { double median;if (small_heap.size() == big_heap.size()) { median = ((double)small_heap.top() + (double)big_heap.top()) / 2; } else if (small_heap.size() < big_heap.size()) { median = (double)big_heap.top();} else { median = (double)small_heap.top();}return median;
}int main() { GetMedian m;int tmp;int n;cout << "input the number of element " << endl;cin >> n;cout << "add " << n << " element 
" << endl;for (int i =0;i < n; ++i) { cin >> tmp;m.push(tmp);}cout << "median is " << m.getMedia() << endl;return 0;
}

输出如下:

input the number of element 
6
add 6 element 3 4 2 1 5 6
median is 3.5input the number of element 
5
add 5 element 6 5 7 3 1
median is 5

更多相关:

  • 中位数是有序列表中间的数。如果列表长度是偶数,中位数则是中间两个数的平均值。 例如, [2,3,4] 的中位数是 3 [2,3] 的中位数是 (2 + 3) / 2 = 2.5 设计一个支持以下两种操作的数据结构: void addNum(int num) - 从数据流中添加一个整数到数据结构中。 double findMedia...

  • 栈stack:stack 后入先出(LIFO) q.top()获取栈顶元素(并不删除)q.pop()删除栈顶元素q.push(x)向栈中加入元素q.empty()判断栈是否为空 队列queue:先入先出(FIFO)   q.front()获取队首元素(并不删除)q.pop()删除队首元素q.push(x)向队列中加入元素q....

  • resize(),设置大小(size); reserve(),设置容量(capacity); size()是分配容器的内存大小,而capacity()只是设置容器容量大小,但并没有真正分配内存。 打个比方:正在建造的一辆公交车,车里面可以设置40个座椅(reserve(40);),这是它的容量,但并不是说它里面就有了40个座椅,只能说...

  • v-for="(index,$i) in total" :key="$i":style="{left:`${itemWidth*((index-1)%rowItemCount)}px`,top:`${itemHeight*(Math.ceil(index/rowItemCount)-1)}px`}" //total是显示总数量 //l...

  •   技巧一(推荐指数★★★★★) 采用top、right、bottom、left,可以不在乎父元素的宽度和高度,对GPU损耗低于技巧三,但是对浏览器内存的消耗高于技巧三 .子元素 {/*父元素需要position: relative|absolute;*/position: absolute;margin: auto;to...

  • 设计一个支持 push,pop,top 操作,并能在常数时间内检索到最小元素的栈。 push(x) – 将元素 x 推入栈中。pop() – 删除栈顶的元素。top() – 获取栈顶元素。getMin() – 检索栈中的最小元素。 示例: MinStack minStack = new MinStack(); minStack...

  • 给定一个以字符串表示的非负整数 num,移除这个数中的 k 位数字,使得剩下的数字最小。 注意: num 的长度小于 10002 且 ≥ k。 num 不会包含任何前导零。 示例 1 : 输入: num = “1432219”, k = 3 输出: “1219” 解释: 移除掉三个数字 4, 3, 和 2形成一个新的最小的数...

  • 代码展示:   http://paste.ubuntu.com/23693598/ #include #include #include char * largeDiffer(char *a,char *b){ /*  使用说明 传入的a和b只能为整数 结果为a-b;返回...

  • Description We all know that Bin-Laden is a notorious terrorist, and he has disappeared for a long time. But recently, it is reported that he hides in Hang Zhou of Ch...

  • /*Name: NYOJ--811--变态最大值Author: shen_渊 Date: 17/04/17 15:49Description: 看到博客上这道题浏览量最高,原来的代码就看不下去了 o(╯□╰)o */#include #include #include u...

  • 生成唯一号:思路,根据yymmddhhmmss+自增长号+唯一服务器号( SystemNo)生成唯一码,总长度19,例如:1509281204550000101. public class UniqueNumber {     private static long num = 0;//流水号     private sta...