按快速排序算法求数组中第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大的集合的数量,再减去基数。
按照这个思路:
- 首先要将数组分成两个比基准数大和小的两个集合,可以运用快速排序算法的思想。
如果想了解快速排序算法,可以看我的博客中有快速排序算法。 - 然后就是按照返回的比基准数大集合的大小与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大值(递归)的主要内容,如果未能解决你的问题,请参考以下文章