一个由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)个最小元素。
本文介绍了一种在平均和最坏情况下都能达到线性时间复杂度的选择算法,用于找到未排序数组中的第i小元素。文章详细展示了算法的实现过程,包括如何划分数组、寻找中位数以及递归应用选择算法。

被折叠的 条评论
为什么被折叠?



