算法导论:第9章 中位数和顺序统计量_1期望为线性时间的选择算法

本文介绍了一种解决选择问题的线性时间选择算法,它是一种分治算法,与快速排序不同,仅处理划分后的其中一个部分。文章详细阐述了算法的时间复杂度、实现方法及过程,并提供了完整的C++代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

/*
线性时间选择算法:
含义:是解决选择问题的分治算法
与快速排序不同的是:快排递归处理划分的两边,而线性选择只对其中
的一个部分进行处理
时间复杂度:O(n)
实现:需要用到随机划分函数
主要的过程好似:A[p...r]通过随机划分函数得到枢轴q
根据划分的两个区间A[p...q-1],A[q],A[q+1...r]
然后判断<=A[q]的元素数量k=q-p+1 与 需要寻找的第i小的关系
如果 k == i,直接返回A[q]
如果 k > i,说明第i小的元素只可能在区间A[p...q-1]中
如果 k < i ,说明第i小的元素在区间A[q+1...r]中 ,并且问题转化为在A[q+1...r]中寻找第i-k小的元素

输入的第一行的第一个数n表示数组元素个数,第二个数i表示该数组中第i小的数
输入:
7 3
329 457 657 839 436 720 355
输出:
436
*/

#include <iostream>
#include <stdlib.h>
#include <stdlib.h>

using namespace std;

//返回iMin~iMax中的任意数字
int myrandom(int iMin,int iMax)
{
	// 3~6,6-3=3 ,
	int iResult = rand() % (iMax - iMin + 1) + iMin;
	return iResult;
}

void swap(int* pArr , int p , int q)
{
	int iTemp = pArr[p];
	pArr[p] = pArr[q];
	pArr[q] = iTemp;
}

int randomPartition(int* pArr,int iLow ,int iHigh)
{
	int iRand = myrandom(iLow , iHigh);
	swap(pArr , iRand , iLow);
	int iPivot = pArr[iLow];
	//下面就是快排的枢轴划分
	while(iLow < iHigh)
	{
		while(iLow < iHigh && pArr[iHigh] >= iPivot)
		{
			iHigh--;
		}
		pArr[iLow] = pArr[iHigh];
		while(iLow < iHigh && pArr[iLow] <= iPivot)
		{
			iLow++;
		}
		pArr[iHigh] = pArr[iLow];
	}
	pArr[iLow] = iPivot;
	return iLow;
}

int randomizedSelect(int* pArr,int p ,int r,int i)
{
	if(p == r)
	{
		return pArr[p];
	}
	int q = randomPartition(pArr, p ,r);
	int k = q - p + 1;
	if(i == k)
	{
		return pArr[q];
	}
	//在低区间
	else if(i < k)
	{
		int iResult = randomizedSelect(pArr, p , q-1 ,i);
		return iResult;
	}
	else
	{
		int iResult = randomizedSelect(pArr , q + 1 , r , i - k);
		return iResult;
	}
}

void process()
{
	int n,u;
	while(cin >> n >> u)
	{
		int* pArr = new int[n];
		for(int i = 0; i < n ; i++)
		{
			cin >> pArr[i];
		}
		int iResult = randomizedSelect(pArr, 0 , n -1 , u);
		cout << iResult << endl;
		delete[] pArr;
	}
}

int main(int argc,char* argv[])
{
	process();
	getchar();
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值