无序数组的中位数(三种方法)

一.利用排序进行查找中位数

基本思路:对数组进行排序,直接访问数组中位数

double MIDnum(vector<int>& array) {
    if(array.empty())
        return -1;
	int midIndex = (array.size() - 1) / 2;
	sort(array.begin(), array.end());
	if (array.size() % 2 == 1) {
		return (double)array[midIndex];
	}
	return ((double)array[midIndex] + (double)array[midIndex + 1]) / 2;
}

二.类似于快速排序,采用的是分而治之的思想.

基本思路:任意挑选一个元素,以该元素为基准点,将数组分为两部分.左部分都是小于基准点的,右部分都是大于基准点的.如果运气好的话,基准值正好就是中位数.

int partion(vector<int>& array, int begin, int end) {
	int start = begin;
	int key = array[begin];
	while (begin < end) {
		while (begin < end && array[end] >= key) {
			end--;
		}
		while (begin < end && array[begin] <= key) {
			begin++;
		}
		swap(array[begin], array[end]);
	}
	swap(array[start], array[begin]);
	return begin;
}	

double getNum(vector<int>& array, int midIndex) {
	int left = 0;
	int right = array.size() - 1;
	int index = -1;
	while (index != midIndex) {
		index = partion(array, left, right);
		if (index > midIndex) {
			right = index - 1;
		}
		else if (index < midIndex) {
			left = index + 1;
		}
		else
			break;
	}
	return (double)array[index];
}
double midNum(vector<int>& array) {
	if (array.empty()) {
		return -1;
	}
	int midIndex = (array.size() - 1) / 2;
	if (array.size() % 2 == 1) {
		return getNum(array, midIndex);
	}
	return (getNum(array, midIndex) + getNum(array, midIndex + 1)) / 2;
}

三.利用最小堆查找中位数

基本思路:首先将数组的前(n+1)/2个元素建立最小堆.后序元素进行判断入堆或舍弃.下一个元素与堆顶元素进行对比,如果大于堆顶元素则删除堆顶元素,该元素入堆,否则什么都不做.

double MidNum(vector<int>& array) {
    if(array.empty())
        return -1;
	int sz = array.size() / 2 + 1;
	cout << sz << endl;
	priority_queue<int,vector<int>,greater<int>> pq;
	for (int i = 0; i < sz; i++) {
		pq.push(array[i]);
	}
	for (int i = sz; i < array.size(); i++) {
		if (array[i] > pq.top()) {
			pq.pop();
			pq.push(array[i]);
		}
	}
	if (array.size() % 2 == 1) {
		return (double)pq.top();
	}
	double val1 = double(pq.top());
	pq.pop();
	double val2 = double(pq.top());
	return (val1 + val2) / 2;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值