确定N个数中的第k大元素-数据结构与算法分析-C语言描述 Mark Allen Weiss-第一章练习题


/*



具体方法:使用类似快速排序,执行一次快速排序后,
  每次只选择一部分继续执行快速排序,直到找到第K个大元素为止,
  此时这个元素在数组位置后面的元素即所求

时间复杂度:
  若随机选取枢纽,线性期望时间O(N)
  若选取数组的“中位数的中位数”作为枢纽,最坏情况下的时间复杂度O(N)
  利用快速排序的思想,从数组S中随机找出一个元素X,把数组分为两部分Sa和Sb。
  Sa中的元素大于等于X,Sb中元素小于X。这时有两种情况:
    1. Sa中元素的个数小于k,则Sb中的第k-|Sa|个元素即为第k大数;
    2. Sa中元素的个数大于等于k,则返回Sa中的第k大数。
    利用快排的partion思想 T(n) = 2T(n/2) + O(1)   时间复杂度为O(n)
    该方法只有当我们可以修改输入的数组时可用,
    位于数组左边的k个数字就是最小的k个数字(但这k个数字不一定是排序的),
    位于第k个数右边的数字都比第k个数字大
*/

#include 
#include 
using namespace std;
int Partition(vector<int> &v,int left,int right){
	int tmp=v[left];
	while(left<right){
		while(left<right&&v[right]<=tmp) right--;
		v[left]=v[right];
		while(left<right&&v[left]>=tmp) left++;
		v[right]=v[left];
	}
	v[left]=tmp;
	return left;
}

int findk(int k,vector<int> v,int left,int right){
	int mid=Partition(v,left,right);
	if(mid==k-1) return v[mid];
	else if(mid<k-1) return findk(k,v,mid+1,right);
	else return findk(k,v,left,mid-1);
}

int main(){
	int k;
	while(1){
		vector<int> v={15,25,9,48,36,100,58,99,126,5};
		int len=v.size();
		cout<<"排序前:"<<endl;
		for(int k:v) cout<<k<<" ";
		cout<<endl;

		cout<<"请输入你要查找第k大的数:"<<endl;
		cin>>k;
		int kth=findk(k,v,0,len-1); //查找第k大的数
		cout<<"第"<<k<<"大数:"<<kth<<endl;

		cout<<endl;
	}

	return 0;
}

你可能感兴趣的:(Algorithms)