数据流中的中位数

数据流中的中位数

题目描述

如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。
解题思路:维护一个大堆和一个小堆,大堆表示序列前一半数,小堆表示序列后一半数,保持两个堆的元素个数之差小于等于1,也就是说大堆的元素个数比小堆多1个,或者两个堆相等。


#include<iostream>
#include <queue>
#include <algorithm>
#include<functional>
using namespace std;

//在进行size减法的时候遇到了一个问题,就是得到的是无符号整数,不能进行判断大小的比较,比如
class Solution {
public:

	priority_queue<int, vector<int>, less<int>> p1;
	priority_queue<int, vector<int>, greater<int>> p2;

	void Insert(int num)
	{
		if (p1.empty() || num <= p1.top())p1.push(num);
		else p2.push(num);
		//p1.size()调用的是priority_queue底层容器vector的size()函数,是无符号整形,
		//如果p1.size()<p2.size(),那么两者进行减法得到的数也是无符号的整数。所以不能用来判断是否大于等于2,
		//需要将其转换为有符号整数int类型才可以
        auto res = p1.size() - p2.size(); //无符号整数
		if ((int)(res) >= 2)    //如果不进行强制类型转换,则如果res在int下为负数的话,在无符号下可能标示为很大的数,那么判断结果也是true,显然不符合
		{
			p2.push(p1.top());
			p1.pop();
		}
		auto res2 = p1.size() - p2.size(); //无符号整数
		if ((int)(res2) == -1)
		{
			p1.push(p2.top());
			p2.pop();
		}

	}

	double GetMedian()
	{
		return p1.size() == p2.size() ? (p1.top() + p2.top()) / 2.0 : p1.top();

	}

};

int main()
{
	int data[] = { 5, 2, 3, 4, 1, 6, 7, 0, 8 };
	vector<int> vec(data,data+9);
	Solution s;
	for (int i = 0; i < 8; i++)
	{
		s.Insert(vec[i]);
		double x = s.GetMedian();
		cout << x << endl;

	}
	system("pause");
	return 0;

}


计算数据流中位数可以通过Flink的ProcessFunction来实现。 具体实现步骤如下: 1. 将数据流按照大小排序 2. 计算数据流的长度,如果是奇数,则中位数为第 (length+1)/2 个元素;如果是偶数,则中位数为第length/2个元素和第(length/2+1)个元素的平均值。 3. 在ProcessFunction的实现中,可以使用状态变量来保存数据流的有序列表,并计算中位数。 以下是一个简单的示例代码: ```java public class MedianFunction extends ProcessFunction<Integer, Double> { private ListState<Integer> values; @Override public void open(Configuration parameters) throws Exception { super.open(parameters); values = getRuntimeContext().getListState(new ListStateDescriptor<Integer>("values", Integer.class)); } @Override public void processElement(Integer value, Context ctx, Collector<Double> out) throws Exception { values.add(value); List<Integer> sortedValues = new ArrayList<>(); for (Integer v : values.get()) { sortedValues.add(v); } Collections.sort(sortedValues); int length = sortedValues.size(); if (length % 2 == 0) { double median = (sortedValues.get(length/2) + sortedValues.get(length/2 - 1)) / 2.0; out.collect(median); } else { double median = sortedValues.get(length/2); out.collect(median); } } } ``` 在上述代码中,我们使用了ListState来保存数据流中的元素,并在每次处理新元素时重新排序并计算中位数。注意,这只是一个简单的示例,实际应用中需要考虑更多的问题,比如数据倾斜、数据丢失等。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值