一个由n个元素组成的集合的第i个顺序统计就是该集合的第i小元素。
中位数:在i = ⌊(n + 1)/2⌋和⌈(n + 1)/2⌉处。(i = 1, 2, ... , n)
选择问题:
输入:一个含n个(不同的)数的集合A和一个数i,1 ≤ i≤ n。
输出:恰大于A中其他i-1个元素的x,(x ∈ A)。
一、求最大最小元

/**//*
*Copyright(c) 2008 All rights reserved.
*
*MaxMin
*Author:Greentea
*Date:01.21
*/
#include <stdio.h>

struct data

...{
int min, max;
};

typedef struct data data;

data MaxMin(int *a, int size)

...{
data temp, l, r;
int disize;

if(size == 1)

...{
temp.min = temp.max = a[0];
return temp;
}
else if(size == 2)

...{
if(a[0] < a[1])

...{
temp.min = a[0];
temp.max = a[1];
}
else

...{
temp.min = a[1];
temp.max = a[0];
}
return temp;
}
else

...{
disize = size / 2;
l = MaxMin(a, disize);
r = MaxMin(a+disize, size-disize);
if(l.max > r.max)
temp.max = l.max;
else
temp.max = r.max;

if(l.min < r.min)
temp.min = l.min;
else
temp.min = r.min;

return temp;
}
}

int main(int argc, char **argv)

...{
int a[100];
int size, i;
data m;

i = 0;
scanf("%d", &size);
while(i < size)
scanf("%d", &a[i++]);
m = MaxMin(a, size);
printf("Min = %d, Max = %d ", m.min, m.max);

return 0;
}
二、以线形期望时间做选择

/**//*
*Copyright(c) 2008 All rights reserved.
*
*Quick Sort
*Author:Greentea
*Date:01.21
*/
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int RandomizedPartition(int *a, int p, int r);
int Random(int low, int high);
void Exchange(int *a, int *b);
int Partition(int *a, int p, int r);
int RandomizedSelect(int *a, int p, int r, int i);


/**//*
*产生介于low - high之间的随机数包括low和high
*Return: random_num
*/
int Random(int low, int high)

...{
int random_num;

srand((unsigned)time(NULL));
random_num = (rand() % (high - low + 1)) + low;

return random_num;
}

void Exchange(int *a, int *b)

...{
int temp;
temp = *a;
*a = *b;
*b = temp;
}

int Partition(int *a, int p, int r)

...{
int i, j, x;

i = p - 1;
x = a[r];
for(j = p; j < r; j++)

...{
if(a[j] <= x)

...{
i++;
Exchange(&a[i], &a[j]);
}
}
Exchange(&a[i+1], &a[r]);

return i+1;
}

int RandomizedPartition(int *a, int p, int r)

...{
int i;

i = Random(p, r);
Exchange(&a[i], &a[r]);

return Partition(a, p, r);
}

int RandomizedSelect(int *a, int p, int r, int i)

...{
int q, k;

if(p == r)
return a[p];
q = RandomizedPartition(a, p, r);
k = q - p + 1;
if(i == k)
return a[q];
else if(i < k)
return RandomizedSelect(a, p, q-1, i);
else
return RandomizedSelect(a, q+1, r, i-k);
}

int main(int argc, char **argv)

...{
int i, temp;

int A[10] = ...{5, 4, 9, 0, 23, 3, 6, 1, 2, 10};
scanf("%d", &i);
temp = RandomizedSelect(A, 0, 9, i);
printf("第%d小元素是%d ", i, temp);

return 0;
}
三、最坏情况线性时间的选择
Select通过执行下列步骤来确定长度为n输入数组中的第i小的元素:
1.将输入数组的n个元素划分成
⌊n/5⌋组,每组5个元素,且至多只有一个组包含余下的n mod 5个元素。
2.通过插入排序来找出每组的中位数,并取其中间元素。
3.对第2步中找出的⌈n/5⌉个中位数,递归调用Select以找出其中位数x。
4.用修改的Partition版本,按x来对输入数组进行划分。
5.若i = k,则返回x。否则,若i < k,则在低区递归调用Select以找出第i小的元素;若i > k,则在高区找第(i - k)个最小元素。