• 検索結果がありません。

Quick Sort 計算機アルゴリズム特論 :2017 年度 只木進一

N/A
N/A
Protected

Academic year: 2021

シェア "Quick Sort 計算機アルゴリズム特論 :2017 年度 只木進一"

Copied!
22
0
0

読み込み中.... (全文を見る)

全文

(1)

Quick Sort

計算機アルゴリズム特論:2017年度

只木進一

(2)

基本的考え方

リスト(あるいは配列)𝑆𝑆の中の、あ

る要素𝑥𝑥(pivot)を選択

𝑥𝑥より小さい要素からなる部分リスト𝑆𝑆

1

𝑥𝑥より大きい要素からなる部分リスト𝑆𝑆

2

𝑥𝑥は𝑆𝑆

1

または𝑆𝑆

2

に含まれる

長さが1になるまで繰り返す

pivot 𝑥𝑥の選び方として、中央の要素

を選択すると効率が良い

2

(3)

三つの可能性

pivotを中央の要素とした場合

pivotの両側の入れ替えるべき要素数

が同じ場合:例1

pivotの位置より、左側にある移動す

べき要素が右側のそれより多い場合:

例2

pivotの位置より、左側にある移動す

べき要素が右側のそれより少ない場

合:例3

3

(4)

左端から𝑥𝑥

𝑖𝑖

≥ 𝑥𝑥となる要素を探す

右端から𝑥𝑥

𝑗𝑗

≤ 𝑥𝑥となる要素を探す

𝑥𝑥

𝑖𝑖

と𝑥𝑥

𝑗𝑗

を入れ替える

𝑖𝑖 < 𝑗𝑗である限り繰り返す

𝑆𝑆

1

= 𝑥𝑥

𝑘𝑘

0 ≤ 𝑘𝑘 < 𝑖𝑖

𝑆𝑆

2

= {𝑥𝑥

𝑘𝑘

|𝑖𝑖 ≤ 𝑘𝑘 < 𝑆𝑆 }

4

(5)

例1

40

30

22

18

51

22

11

45

32

19

15

基準値

左端から基準値以上となる最初の要素(

32

)の位置𝑖𝑖

右端から基準値以下となる最初の要素(

22

)の位置𝑗𝑗

二つの要素を入れ替える

𝑖𝑖

𝑗𝑗

40

30

32

18

51

22

11

45

22

19

15

位置𝑖𝑖から基準値以上となる最初の要素(

45

)の位置𝑖𝑖

位置𝑗𝑗から基準値以下となる最初の要素(

18

)の位置𝑗𝑗

二つの要素を入れ替える

𝑖𝑖

𝑗𝑗

5

(6)

40

30

32

45

51

22

11

18

22

19

15

位置𝑖𝑖から基準値以上となる最初の要素(

22

)の位置𝑖𝑖

位置𝑗𝑗から基準値以下となる最初の要素(

22

)の位置𝑗𝑗

𝑖𝑖 ≥ 𝑗𝑗となったので、𝑖𝑖で分割

𝑖𝑖 𝑗𝑗

40

30

32

45

51

22

11

18

22

19

15

6

基準値より小さい

基準値以上

(7)

例2

40

30

22

37

51

23

11

45

32

19

25

基準値

左端から基準値以上となる最初の要素(

25

)の位置𝑖𝑖

右端から基準値以下となる最初の要素(

22

)の位置𝑗𝑗

二つの要素を入れ替える

𝑖𝑖

𝑗𝑗

40

30

25

37

51

23

11

45

32

19

22

位置𝑖𝑖から基準値以上となる最初の要素(

32

)の位置𝑖𝑖

位置𝑗𝑗から基準値以下となる最初の要素(

23

)の位置𝑗𝑗

二つの要素を入れ替える

𝑖𝑖

𝑗𝑗

7

(8)

40

30

25

37

51

32

11

45

23

19

22

位置𝑖𝑖から基準値以上となる最初の要素(

45

)の位置𝑖𝑖

位置𝑗𝑗から基準値以下となる最初の要素(

11

)の位置𝑗𝑗

二つの要素を入れ替える

𝑖𝑖

𝑗𝑗

40

30

25

37

51

32

45

11

23

19

22

位置𝑖𝑖から基準値以上となる最初の要素(

45

)の位置𝑖𝑖

位置𝑗𝑗から基準値以下となる最初の要素(

11

)の位置𝑗𝑗

𝑖𝑖 ≥ 𝑗𝑗となったので、𝑖𝑖で分割

40

30

25

37

51

32

45

11

23

19

22

𝑖𝑖

𝑗𝑗

基準値以下

基準値より大きい

8

(9)

例3

40

30

20

18

51

22

11

15

12

19

15

基準値

左端から基準値以上となる最初の要素(

22

)の位置𝑖𝑖

右端から基準値以下となる最初の要素(

20

)の位置𝑗𝑗

二つの要素を入れ替える

𝑖𝑖

𝑗𝑗

位置𝑖𝑖から基準値以上となる最初の要素(

51

)の位置𝑖𝑖

位置𝑗𝑗から基準値以下となる最初の要素(

18

)の位置𝑗𝑗

二つの要素を入れ替える

𝑖𝑖 𝑗𝑗

40

30

22

18

51

20

11

15

12

19

15

9

(10)

40

30

22

51

18

20

11

15

12

19

15

位置𝑖𝑖から基準値以上となる最初の要素(

51

)の位置𝑖𝑖

位置𝑗𝑗から基準値以下となる最初の要素(

18

)の位置𝑗𝑗

𝑖𝑖 ≥ 𝑗𝑗となったので、𝑖𝑖で分割

𝑖𝑖

𝑗𝑗

40

30

22

51

18

20

11

15

12

19

15

10

基準値より小さい

基準値以上

(11)

public T[] doSort() {

sortSub(0, data.length);

return data;

}

protected void sortSub(int begin, int end) {

if (end <= begin + 1) {

return;

}

int

boundary

= partition(begin, end);

sortSub(begin,

boundary

);

sortSub(boundary

, end);

}

(12)

protected int partition(int begin, int end) {

int fromLeft = begin - 1;

int fromRight = end;

int m = (begin + end) / 2;

T v = data[m];

for (;;) {

while (less(data[++fromLeft], v));

while (less(v, data[--fromRight])) {

if (fromRight == begin) { break; }

}

if (fromLeft >= fromRight) {break; }

exch(fromLeft, fromRight);

}

return fromLeft;

}

(13)

注:increment/decrement演

算子

𝑏𝑏 = 𝑎𝑎 + +;

𝑎𝑎を𝑏𝑏へ代入後、インクリメント

𝑏𝑏 =+ +𝑎𝑎;

𝑎𝑎をインクリメント後、𝑏𝑏へ代入

while (less(data[++fromLeft], v));

vより小さくない要素を見つけるまで、

fromLeftをインクリメント

13

(14)

計算量

一回のpartition操作で、要素の比較は

𝑛𝑛回

partitioningは、概ねlog

2

𝑛𝑛回

全体で𝑛𝑛log

2

𝑛𝑛回の比較

要素をswapするために、作業領域を

必要としない

14

(15)

比較回数

15

(16)

入替回数

16

(17)

pivotの選択を最後の要素にし

た場合

17

22

11

15

18

30

20

11

15

12

19

15

基準値

左端から基準値以上となる最初の要素(

22

)の位置𝑖𝑖

右端から基準値以下となる最初の要素(

20

)の位置𝑗𝑗

二つの要素を入れ替える

𝑖𝑖

𝑗𝑗

20

11

15

18

30

22

11

15

12

19

15

𝑗𝑗

𝑖𝑖

位置𝑖𝑖から基準値以上となる最初の要素(

30

)の位置𝑖𝑖

位置𝑗𝑗から基準値以下となる最初の要素(

11

)の位置𝑗𝑗

二つの要素を入れ替える

(18)

18

22

30

15

18

11

20

11

15

12

19

15

𝑗𝑗 𝑖𝑖

位置𝑖𝑖から基準値以上となる最初の要素(

30

)の位置𝑖𝑖

位置𝑗𝑗から基準値以下となる最初の要素(

15

)の位置𝑗𝑗

𝑖𝑖 ≥ 𝑗𝑗となったので、𝑖𝑖で分割

22

30

15

18

11

20

11

15

12

19

15

(19)
(20)

QuickSort.java

package sort;

import java.io.IOException;

import java.util.function.BinaryOperator;

import static sort.AbstractSort.testRun;

/** *

* @author tadaki * @param <T> */

public class QuickSort<T extends Comparable<T>> extends AbstractSort<T> { //pivotの選び方

public static enum PivotType { Middle, First, Last, Random; }

public static final boolean debug = false; //pivot を選ぶ関数のデフォルト

private BinaryOperator<Integer> getPivot = (begin, end) -> (begin + end) / 2; public QuickSort(T[] data) {

super(data); } public QuickSort() { } /** * pivotを変更する * * @param pivotType */

public void setPivotType(PivotType pivotType) { switch (pivotType) {

case First://最初の要素

getPivot = (begin, end) -> begin; break;

case Last://最後の要素

getPivot = (begin, end) -> end - 1; break;

case Random://ランダム

getPivot = (begin, end)

-> (int) ((end - begin) * Math.random()) + begin; break;

(21)

QuickSort.java

default://中央の要素

getPivot = (begin, end) -> (begin + end) / 2; break; } } @Override public T[] doSort() { sortSub(0, data.length); return data; }

protected void sortSub(int begin, int end) { if (end <= begin + 1) {

return; }

int boundary = partition(begin, end); sortSub(begin, boundary); sortSub(boundary, end); } /** * pivotの値での分割 * * @param begin 配列の開始位置 * @param end 終了位置:対象の外側であることに注意 * @return 分割の位置 */

protected int partition(int begin, int end) { int fromLeft = begin - 1;

int fromRight = end;

int m = getPivot.apply(begin, end); T v = data[m];

if (debug) {

System.out.print("partition (" + begin + "," + end + ") "); System.out.println("with pivot " + v + " at " + m);

}

for (;;) {

while (less(data[++fromLeft], v)); while (less(v, data[--fromRight])) { if (fromRight == begin) { break; } } if (fromLeft >= fromRight) { break; 2/3 ページ

(22)

QuickSort.java }

if (debug) {

System.out.println(data2Str()

+ ":swap(" + fromLeft + "," + fromRight + ")"); }

exch(fromLeft, fromRight); }

if (debug) {

System.out.println("end paritioning with " + data2Str()); } return fromLeft; } /** * 配列の文字列化 * * @return */

private String data2Str() {

StringBuilder sb = new StringBuilder(); sb.append("[");

for (int i = 0; i < data.length - 1; i++) { sb.append(data[i]).append(","); } sb.append(data[data.length - 1]).append("]"); return sb.toString(); } /**

* @param args the command line arguments * @throws java.io.IOException

*/

static public void main(String args[]) throws IOException { if (QuickSort.debug) {

Integer[] data = {15, 19, 12, 15, 11, 22, 30, 18, 15, 11, 20}; QuickSort<Integer> qs = new QuickSort<>(data);

qs.doSort(); } else {

int numData = 1000;

Data[] data = Data.createData(numData); testRun(new QuickSort<>(data));

} } }

参照

関連したドキュメント

年度 2015 2016 2017

総合図 製作図 改善 トラブルシューティ ング 基本図 総合図 一品図 製作図 2D-CAD. コンテナ関連

年度 2010 ~ 2013 2014 2015 2016 2017 2018 2019.

 現在 2016年度 2017年度 2018年度 2019年度 2020年度

年度 2013 2014 2015 2016

 現在 2016年度 2017年度 2018年度 2019年度 2020年度

2014年度 2015年度 2016年度 2017年度 2018年度 2019年度 2020年度

2014年度 2015年度 2016年度 2017年度 2018年度 2019年度 2020年度