按快速排序算法求数组中第K大值(递归)

Posted 两片空白

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了按快速排序算法求数组中第K大值(递归)相关的知识,希望对你有一定的参考价值。

这几天在看浙江大学陈越的那本数据结构这本书,看到第二章里有一个求书中有求集合中第K大数的问题。按照它的思路,我想来试一试。

思路:用一个基准数e,将集合S分解为两个不包含e在内的两个小集合S1和S2,其中S1中任何元素均大于等于e,S2中任何元素均小于e。记S1长度为len,如果len>=K,则说明第K大数在S1中,如果len=K-1,那么e是第K大数,否则第K大数在S2中,并且是第K-len-1大数。

这是教材中的思路。但是我的做法与这个有一些不同。

首先我先解释一下,为啥在S2中是求K-len-1大数:
为什么比基数小的数组里是求第 K-len(比基数大的数组)-1    
在比基数小的数组中,要找的数在里面第几大数变了,减去比 k大的集合的数量,再减去基数。

按照这个思路:

  1. 首先要将数组分成两个比基准数大和小的两个集合,可以运用快速排序算法的思想。
    如果想了解快速排序算法,可以看我的博客中有快速排序算法
  2. 然后就是按照返回的比基准数大集合的大小与K值作比较,重新设立递归条件。

代码:

基准总取数组最左边这个数,注意不是第0个数。
将大于等于的基准数的数放原数组前面,返回的right,就是大于等于的基准数数组的大小。

注意:我这里于教材思路不同的地方在于,不是将数组划分成了两个数组,还是在一个数组中,当第K大值在比基准数小的数组中时,还是求第K个数的大小,不是第K-len-1个数的大小。

#include<stdio.h>
#include<Windows.h>
#pragma warning(disable:4996)
//按快速排序算法求数组最大K值
int Swap(int arr[], int left, int right){//将比基准数大的数放前面,将比基准数小的数放后面
	int temp = arr[left];
	while (left < right){
		while (temp >= arr[right] && left < right){
			right--;
		}
		arr[left] = arr[right];
		while (temp <= arr[left] && left < right){
			left++;
		}
		arr[right] = arr[left];
	}
	arr[right] = temp;//基准数放中间
	return right;
}

static int Findklargest(int a[], int left,int right, int k){
	int temp = Swap(a, left, right);//返回的是比基数大的数组的大小
	if (temp >= k)
		return Findklargest(a, left, temp - 1, k);//第k个值在大数数组这边
	else if (temp < k - 1)
		return Findklargest(a, temp + 1, right, k);//第k个数在小数数组这边,还是求第k个数的大小
	else
		return a[temp];
	return -1}

int main(){
	int a[] = { 5, 1, 2, 3, 8, 7, 6, 9, 5, 4, 3 };
	int num = sizeof(a) / sizeof(a[0]);
	int k = 0;
	scanf("%d", &k);
	int result = Findklargest(a, 0, num - 1, k);
	printf("%d\\n", result);
	system("pause");
	return 0;
}

以上是关于按快速排序算法求数组中第K大值(递归)的主要内容,如果未能解决你的问题,请参考以下文章

排序算法——快速排序

排序算法——快速排序

快速排序算法及其思想的应用(寻找一个序列中第k小元素)

找出n个有序数组中第K小的数。怎么写算法啊?各位帮帮忙!

快速排序-递归实现

求数组中第K个最大的值