push_swapを
理解するためのスライド
作成者:nfukada(nafuka11)
1
おしながき
2
push_swapとはどんな課題か
3
push_swapを一言で表すと
与えられた数値をソートするプログラムを作る課題
4
データ構造のスタック
wikipedia より
スタックは、コンピュータで用いられる基本的なデータ構造の1つで、データを後入れ先出し(LIFO: Last In First Out; FILO: First In Last Out)の構造で保持するもの
5
push_swapの�スタック
初期状態(引数から与えられる)
+--------a--------+--------b--------+
|[ 2]3 | |
|[ 0]1 | |
|[ 1]2 | |
+-----------------+-----------------+
↓
こうしたい
+--------a--------+--------b--------+
|[ 0]1 | |
|[ 1]2 | |
|[ 2]3 | |
+-----------------+-----------------+
6
専用の命令
全部で11個。大まかな系統は以下
詳細は、Push_Swap: The least amount of moves with two stacks | by Jamie Dawson | Medium の図が分かりやすいです
7
2つのプログラム
push_swap
checker
8
プログラム実行例
# push_swapとcheckerの動作
$ ./push_swap 3 2 1
sa
rra
$ ./checker 3 2 1
(標準入力を受け付ける)
# push_swapとcheckerをパイプでつないで動作確認
$ ./push_swap 3 2 1 | ./checker 3 2 1
(OKかKOを表示する)
# 引数が数値でない or intの範囲を超えてたらErrorと表示
$ ./push_swap a
Error
$ ./push_swap 2147483648
Error
# 引数なしは何もしない
$ ./checker
$
9
データ構造
10
今回使ったデータ構造:双方向循環リスト
双方向循環リスト = 連結リスト + 双方向 + 循環
11
双方向循環リストを使った理由
要素の追加削除を頻繁に行う → 連結リスト
先頭と先頭の次、末尾にアクセスする必要あり → 双方向
回転、逆回転する → 循環
12
双方向循環リスト:図で表すと
1つの要素をノードという
nilは番兵ノード
13
双方向循環リスト:番兵ノード
要素がないときは → のような感じになる
14
アルゴリズム
15
分割統治法
そのままでは解決できない大きな問題を
小さな問題に分割して全て解決することで
大きな問題を解決する
16
クイックソート
分割統治法を使った�ソートアルゴリズム
17
push_swapの実装
18
push_swapの実装
要素数3個以下、6個以下、7個以上で場合分け
6個以下はルールベース。7個以上はクイックソートする
共通の考え方
19
push_swapの流れ:3個以下のとき
参考:Push_Swap: The least amount of moves with two stacks | by Jamie Dawson | Medium の「3 random numbers」
20
push_swapの流れ:6個以下のとき
21
push_swapの流れ:7個以上のとき
aの末尾へ小さい順に数字を挿入し、ソート済み扱いにしていく
22
左の初期状態から右の状態にしたい
23
2. aを大小で分けbへpush
24
3. bを分割できなくなるまで� aへpush
4. bをaの末尾へ
5. aからbへpushして戻す
25
bへpush, aへpush, aの末尾へ追加, を繰り返して……
26
最終的に全てがソートされる
27
細かな最適化
28
参考書籍・URL
アルゴリズム
push_swap
ビジュアライザー
29
ありがとうございました!
不明点などありましたら、Discordにてお願いします
30