For a given n-element array of a[0:n-1], it is required to find the element K small from it. When A[0:n-1] is sorted, the element is a[k-1]. Suppose n=8, each element has two domains K e y and I d, where K e y is an integer, I D is a character. Suppose that these 8 elements are [(1 2, a), (4, B), (5, C), (4, D), (5, E), (1 0, F), (2, G), (2 0, h)], sorted after the array [(2, G), (4, D), (4, B), (5, C), ( 5, E), (1 0, F), (1 2, a), (2 0, H)]. If the k=1, return the element i d is g; if k=8, return the element i d is h, and if k=6, return the element with I d as f, and if k=2, return the element i d to D. In fact, in the last case, the results may not be unique, because it is possible to rank the elements D in a[1] in the sort process, you may also rank the elements i d to B in a[1] because they have the same size K e y, so that any one of the two elements is likely to be returned. However, if an element is returned at k=2, the other must be returned at k=3 time.
One application of the choice problem is to find the median element, at this point K=[N/2]. Median is a very useful statistic, such as median wage, middle age, middle weight. Other k values are also useful. For example, by looking for the three elements of N/4, N/2 and 3 N/4, the population can be divided into 4 parts.
The selection problem can be resolved in O (n l o G) time by first sorting the n elements (such as using a heap sort or merge sort), and then removing the elements from a[k-1. If you use a quick sort (shown in Figure 1 4-11), you get better average performance, although the algorithm has a poor asymptotic complexity O (n2).
You can fix the selection problem by writing the program 1 4-6. If the fulcrum element A[l] is exchanged to a[j after executing two w h i l e loops, then a[l] is the J-l + 1 element in A[l:j]. If you are looking for the K element in A[l:r], and j-l + 1 equals k, then the answer is a[l]; if j-l + 1 <k, then the search element is the K-j + l-1 element in R i g H T, otherwise the element to be looked for is the K element in the left 。 Therefore, only 0 or 1 recursive calls are required. The new code is shown in program 1 4-7. Recursive calls in S e l e c T can be replaced with F o r or W h i l e loops (Exercise 2 5).
Program 14-7 looking for the K element
template
T Select(T a[], int n, int k)
{// 返回a[0 : n - 1]中第k小的元素
// 假定a[n]是一个伪最大元素
if(k <1 || k >n) throw OutOfBounds();
return select(a, 0, n-1, k);
}
template
T select(T a[], int l, int r, int k)
{// 在a[l : r]中选择第k小的元素
if(l >=r) return a[l];
int i=l, // 从左至右的游标
j=r + 1; // 从右到左的游标
T pivot=a[l];
// 把左侧>=pivot的元素与右侧<=pivot 的元素进行交换
while(true) {
do {// 在左侧寻找>=pivot 的元素
i=i + 1;
} while(a[i] <pivot);
do {// 在右侧寻找<=pivot 的元素
j=j - 1;
} while(a[j] >pivot);
if(i >=j) break; // 未发现交换对象
Swap(a[i], a[j]);
}
if(j - l + 1==k) return pivot;
// 设置p i v o t
a[l]=a[j];
a[j]=pivot;
// 对一个段进行递归调用
if(j - l + 1 <k)
return select(a, j+1, r, k-j+l-1);
else return select(a, l, j-1, k);
}