编程之美--寻找最大的K个数

  方法一.先排序然后找出最大的K个数,这里选择快速排序,代码如下:

int partition(int *arr,int low,int high){//划分函数
	int key=arr[low];
	while(low<high){
		while(low<high&&arr[high]>=key)high--;
		arr[low]=arr[high];
		while(low<high&&arr[low]<=key)low++;
		arr[high]=arr[low];
	}
	arr[low]=key;
	return low;
}
void quickSort(int *arr,int low,int high){//快排
	if(low<high){
		int pivot=partition(arr,low,high);
		quickSort(arr,low,pivot-1);
		quickSort(arr,pivot+1,high);
	}
}

void getKBig(int *arr,int n,int k){
	quickSort(arr,0,n-1);
	if(k>n)//如果k比n大则取摸
		k%=n;
	for(int i=1;i<=k;i++){
		printf("%d ",arr[n-i]);
	}
}

方法二 用部分排序算法,找出最大的K个数。选择排序和冒泡排序都可以,这里选择选择排序,代码如下:

void selectKBig(int *arr,int n,int k){
	if(k>n)//如果k比n大则取摸
		k%=n;
	for(int i=n-1;i>n-k-1;i--){
		int index=0;//找最大的元素下标
		for(int j=1;j<=i;j++){
			if(arr[j]>arr[index])
				index=j;
		}
		if(index!=i){//如果不等则交换
			int temp=arr[index];
			arr[index]=arr[i];
			arr[i]=temp;
		}
	}
    //输出
	for(int i=1;i<=k;i++){
		printf("%d ",arr[n-i]);
	}
}

方法三  利用部分堆排序,建立大小为K的堆,然后遍历其后的元素与堆顶元素比较,若大则交换.代码如下:

//保持最小堆的性质,递归版本
void minHeapify(int *arr,int heapSize,int i){
	int smallest=i;
	int left=(i<<1)+1;
	int right=left+1;
	if(left<heapSize&&arr[left]<arr[smallest])
		smallest=left;
	if(right<heapSize&&arr[right]<arr[smallest])
		smallest=right;
	if(smallest!=i){
		int temp=arr[smallest];
		arr[smallest]=arr[i];
		arr[i]=temp;
		minHeapify(arr,heapSize,smallest);
	}
}

//保持最小堆的性质,非递归版本(迭代版本)
void minHeapify(int *arr,int heapSize,int i){
	int left,right,smallest;
	while(i<heapSize){
		smallest=i;
		left=(i<<1)+1;
		right=left+1;
		if(left<heapSize&&arr[left]<arr[smallest])
			smallest=left;
		if(right<heapSize&&arr[right]<arr[smallest])
			smallest=right;
		if(smallest!=i){
			int temp=arr[smallest];
			arr[smallest]=arr[i];
			arr[i]=temp;
			i=smallest;
		}else
			break;
	}
}

//建堆
void buildHeap(int *arr,int heapSize){
	for(int i=(heapSize-2)/2;i>=0;i--)
		minHeapify(arr,heapSize,i);
}

void getKBig(int *arr,int length,int k){
	if(k>length)
		k%=length;
	buildHeap(arr,k);
	int temp=0;
	for(int i=k;i<length;i++)
		if(arr[i]>arr[0]){
			temp=arr[i];
			arr[i]=arr[0];
			arr[0]=temp;
			minHeapify(arr,k,0);
		}
	for(int j=0;j<k;j++)
		printf("%d ",arr[j]);
}

方法四 利用计数排序思想,但是使用范围较小,其元素必须是整数且不是很大,代码如下:

int getKBig(int *arr,int length,int k){
	//如果大于长度则取摸
	if(k>length)
		k%=length;
	//找最大值
	int max=arr[0],i;
	for(i=1;i<length;i++){
		if(arr[i]>max)
			max=arr[i];
	}
	int *count=new int[max+1];
	//初始化为零
	for(i=0;i<=max;i++)
		count[i]=0;
	//统计每个元素出现的次数
	for(i=0;i<length;i++)
		count[arr[i]]++;
	//统计第K大的数
	int pc=0;
	for(i=max;i>=0;i--){
		pc+=count[i];
		if(pc>=k)
			break;
	}
	//输出
	for(int j=0;j<length;j++)
		if(arr[j]>=i)
			printf("%d ",arr[j]);
	return i;
}

方法五 寻找第K大的数,然后再扫描一趟原数组

//分割
int randomizedPartition(int *A,int low,int high){
	//set the key value
	int key=A[low];
	while(low<high){
		while(low<high&&A[high]>=key)high--;
		A[low]=A[high];
		while(low<high&&A[low]<=key)low++;
		A[high]=A[low];
	}
	A[low]=key;
	return low;
}

//选择第K大的数
int randomizedSelect(int *A,int s,int t,int i){
	if(s==t)
		return A[s];
	int p=randomizedPartition(A,s,t);
	int k=t-p+1;
	if(k==i)
		return A[p];
	else if(k>i)
		return randomizedSelect(A,p+1,t,i);
	else
		return randomizedSelect(A,s,p-1,i-k);
}

//最大的K个数
void getKBig(int *arr,int length,int k){
	if(k>length)
		k%=length;
	int key=randomizedSelect(arr,0,length-1,k);
	//输出
	for(int j=0;j<length;j++)
		if(arr[j]>=key)
			printf("%d ",arr[j]);
}
    原文作者:taihejin
    原文地址: https://blog.csdn.net/taihejin/article/details/18180473
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞