一、问题描述:
设S是n个元素的集合,从S中选取第k小的元素,其中1≤k≤n。这里的第k小的元素是指,当S按从小到大排好序后,排在第k个位置的元素。
采用二分归并排序,然后选择第k小元素。
二、算法核心步骤(伪代码)及图解:
伪代码:
Select(S,k)
输入:n个数的数组S,正整数k;
输出:S中的第k小元素;
1.将S划分为5个一组,共[n/5]个组;
2.每组找一个中位数,把这些中位数放到集合M中;
3.m*<-Select(M,[|M|/2]) //选M中的中位数m*,将S中的数划分成A、B、C、D四个集合;
4.把A和D中的每个元素和m比较,小的构成S1,大的构成S2;
5.S1<-S1∪C,S2<-S2∪B;
6.if k=|S1|+1 then 输出m
7.else if k≤|S1|
then Select(S1,k)
else Select(S2,k-|S1|-1)
三、代码实现:
#include <stdio.h>
#include <stdlib.h>
void merge(int a[],int left,int mid,int right) //二分归并排序
{
int i,k;
int *tmp = (int *)malloc((right-left+1)*sizeof(int));
int left1=left;
int left2=mid;
int right1=mid+1;
int right2=right;
for(k=0;left1<=left2 && right1<=right2;k++)
{
if(a[left1]<=a[right1])
{
tmp[k]=a[left1++];