三默网为您带来有关“算法实验---线性时间选择问题(分治)”的文章内容,供您阅读参考。

算法实验---线性时间选择问题(分治)

2023-01-21 17:17:23

问题描述:
给定一个n个元素序列(乱序),在线性时间内(O(n))找出其中第k大的元素(1<=k<=n);
(输入元素均为double型数据)
输入说明:
第一行输入一个正整数n;
第二行输入n个double型数据代表整个序列;
第三个输入需要查找的第search大的数据(1<=search<=n);
输出说明:
输出这个序列中第search大的元素即可;
input_case1:
6
0.2 3.6 9.6 -1 0 44
4
output_case1:
3.6
input_case2:
10
1.2 0.66 0.99 99.5 -100 20 32.5 44.3 3.12 10.3
6
output_case2:
10.3
input_case3:
16
0.2 3.6 9.6 -1 0 44 1.2 0.66 0.99 99.5 -100 20 32.5 44.3 3.12 10.3
9
output_case3:
3.6

code:

#include<bits/stdc++.h>
using namespace std;

template<class T>
int Partition(T *a,int p,int r,T x){//一次快排的Parition函数 
	int i=p;
	int j=r+1;
	
	while(i<j){
		while(a[++i]<x&&i<r);
		while(a[--j]>x);
		if(i>=j)break;
		swap(a[i],a[j]);
	}
	a[p]=a[j];
	a[j]=x;
	return j;//返回放置的位置 
}

template<class T>
T Select(T *a,int p,int r,int k){//线性时间选择函数 
	if(r-p<=75){//小规模问题直接调用快排即可 
		sort(a,a+(r-p+1));
		return a[p+k-1];
	}else{//较大规模问题分治处理 
		for(int i=0;i<=(r-p-4)/5;i++){//分组排序(每组5个) 
			sort(a+p+4*i,a+(p+4*i+4));
			swap(a[p+i],a[p+4*i+2]);//将中位数调到前面 
		}
		
		T x=Select(a,p,p+(r-p-4)/5,(r-p-4)/10);//x为中位数的中位数 
		int index=Partition(a,p,r,x);//调用一次快排函数 
		int j=index-p+1;//j为左边区间的元素个数 
		if(k>=j)return Select(a,index+1,r,k-j);//对应右区间 
		else Select(a,p,index,k);//对应左区间 
	}
}

int main(){
	
	int n;
	scanf("%d",&n);
	double a[n];
	for(int i=0;i<n;i++){
		scanf("%lf",&a[i]);
	}
	int search;//search代表第几个大的函数 
	cin>>search;
	double mid=Select(a,0,n-1,search);
	cout<<mid<<endl;
	return 0;
}