Sibainu Relax Room

柴犬と過ごす

RUST QuickSortの見直し

だめだったか。おれには関係ないやとマイペースな柴犬です。

sort 部分の見直し

次のようにソート部分を見直しましたが、残念ながら効果は感じられませんでした。

クイックソートから外れますが、構造体を要素にしたベクトルを作ってみて、O’reilly プログラミングRust第2版にある16.2.8 ソートと検索にある次のコードを使ってどのくらいでできるのか確かめたいと思います。

students.sort_by(|a, b| {
    let a_key = (&a.last_name, &a.first_name);
    let b_key = (&b.last_name, &b.first_name);
    a_key.cmp(&b_key)
});

引き続き考えてみます。

copy

fn partition<T: PartialOrd + Clone>(
    elements: &mut Vec<Vec<T>>,
    left: usize,
    right: usize,
) -> usize {
    let pivot1 = elements[left][0].clone();
    let pivot2 = elements[left][1].clone();
    let mut i = left + 1;
    let mut j = right;
    loop {
        // i, j の取り得る範囲は left + 1 <= i, j <= right
        // 条件を満たす限り i を進めます。
        while i <= right
            && (elements[i][0].clone() < pivot1
                || (elements[i][0].clone() == pivot1 && elements[i][1].clone() < pivot2))
        {
            i += 1;
        }
        // 条件を満たす限り j を進めます。
        // 同値に対応するため .clone() > pivot2 を .clone() >= pivot2 としました。
        while j >= left + 1
            && (elements[j][0].clone() > pivot1
                || (elements[j][0].clone() == pivot1 && elements[j][1].clone() >= pivot2))
        {
            j -= 1;
        }
        // 交差になれば入れ替えます。
        if i >= j {
            break;
        }
        swap(elements, i, j);
    }
    // ピボットを正しい位置にセットします。
    swap(elements, left, j);
    return j as usize;
}

fn swap<T: PartialOrd + Clone>(elements: &mut Vec<Vec<T>>, i1: usize, i2: usize) {
    if i1 < i2 {
        let mut temp = elements[i2][0].clone();
        elements[i2][0] = elements[i1][0].clone();
        elements[i1][0] = temp;
        temp = elements[i2][1].clone();
        elements[i2][1] = elements[i1][1].clone();
        elements[i1][1] = temp;
    }
}

fn quicksort<T: PartialOrd + Clone>(elements: &mut Vec<Vec<T>>, left: usize, right: usize) {
    if left < right {
        let pivot = partition(elements, left, right);
        // オーバーフローのエラーがでるが
        // 実際は pivot == 0 になると underflow エラー
        if pivot < 1 {
            quicksort(elements, left, left);
        } else {
            quicksort(elements, left, pivot - 1);
        }
        quicksort(elements, pivot + 1, right);
    }
}

今回の QuickSort

ここで、P、A、B が同値で、P がピボットである下の図の場合を考えてみます。

P をピボットの位置とします。i は条件を満たすか否かを判定しながら右へ進みます。そして条件を満たさない A の位置で止まります。

次に j を考えます。

不等号 > の場合

j は条件を満たすか否かを判定しながら左へ進みます。そして条件を満たさない B の位置で止まります。

この場合、交差は起こらないので A と B の交換が行われます。

しかし、次のループでも i と j は条件を満たさないので進めません。

したがって、無限ループが発生します。

不等号 >= の場合

j は条件を満たすか否かを判定しながら左へ進みます。そして条件を満たさない C の位置で止まります。

この場合、i > j となり交差が発生します。

そして、P と C を交換します。図で分かるとおり C の位置がソートしたときの P の位置です。この位置は今後変わりません。

また、C の位置がピボットより小さい領域、大きい領域を分ける分水嶺となります。