選択アルゴリズムを理解する前に、用語について理解しておき
顺序统计量
ます。セット内で、i番目数序统计量
はセット内のi番目に小さい要素を指します。
選択アルゴリズムが扱う顺序统计量
問題は、n個の要素のセットからi番目の問題を見つけることです。i=3
セット内で3番目に小さい要素を見つける必要がある場合
基本的な考え方
快速排序
のパーティショニングアルゴリズムに基づいて、分割して征服するというアイデアを使用して、検索顺序统计量
する場所に応じて再帰的に解決されます。
- 問題の分解:パーティションアルゴリズム(
快速排序
章を参照)を使用してアレイをパーティション化し、iのパーティション位置を決定し、再帰的に続行します。 - 問題の処理:パーティションサンプルの場所がiに等しい場合、結果を返します。
コード
快速排序
ミドルパーティションアルゴリズムとの違いは、ここでのパーティションアルゴリズムがランダムサンプリング関数を追加することです。詳細については、コードを参照してください。
/**
* 获取数组任意位置的顺序统计量
* @param array 输入数组
* @param pos 查询位置
* @param start 起始位置
* @param end 结束位置
* @return 元素值
*/
private static int randomSelection(int[] array, int pos, int start, int end) {
//获取随机分区的样本位置
int mid = randomPartition(array, start, end);
//递归结束点,当要获取的 pos=mid 时
if (pos == mid) {
return array[mid];
}
System.out.println("start:" + start + "|end:" + end + "|pos:" + pos + "|mid:" + mid);
//递归情况
if (pos < mid) {
return randomSelection(array, pos, start, mid - 1);
} else {
return randomSelection(array, pos, mid + 1, end);
}
}
/**
* 随机分区
* @param array 分区数组
* @param start 起始位置
* @param end 结束位置
* @return 样本位置
*/
private static int randomPartition(int[] array, int start, int end) {
//计算随机样本位置
int samplePos = random(start, end);
//将随机样本放到数组尾部
int temp = array[end];
array[end] = array[samplePos];
array[samplePos] = temp;
int sample = array[end];
//左侧区域默认为空
int leftEnd = start - 1;
//检测到小于样本值的数据,放入左侧区域
for (int i = start; i < end; i++) {
if (array[i] <= sample) {
leftEnd++;
temp = array[leftEnd];
array[leftEnd] = array[i];
array[i] = temp;
}
}
//将样本中放到中间区域
temp = array[end];
array[end] = array[leftEnd + 1];
array[leftEnd + 1] = temp;
return leftEnd + 1;
}
結論
分割して征服するというアイデアは本当に良いですが、このコードは完全には
算法导论
実装されておらず、途中でStackOverflow
例外が発生します。アルゴリズム機能を改善する必要があるようです。