課題をといてみる。
例のごとくです。
課題→ここ
課題81はスタック作ればおっけーなんで省略ー。
課題82
これはちょいとスマートな方法を思いつかんかったわ...。
とりあえず俺が思いついた方法は
// とりあえずroot積んでおく。 stack.push( root ); /* ...(甲) */ // スタックに要素がある限り while( !empty() ) { // 要素をpopする tmp = stack.pop(); /* ...(乙) */ if( /* tmpは既に処理したか? */ ) { // tmpはすでに処理したならプリントする printf( /* ほげほげ */ ); /* ...(丙) */ } else { // tmpがまだ未処理 if( /* 右があるか? */ ) { // あるならつむ。 stack.push( tmp.right ); /* ...(丁) */ } /* tmpは既に処理した、と情報を加える */ // スタックに積む。 stack.push( tmp ); /* ...(戊) */ if( /* 左があるか? */ ) { // あるならつむ。 stack.push( tmp.left ); /* ...(己) */ } } }
こんな感じ。
具体例で説明すると
6 4 8 1 5 7 9
こんなツリーを考えます。
すると(甲〜己はソースコード中のそれ、stackの"[x]"はxは処理済みであることをしめす。
手順 | stack | 出力 |
---|---|---|
甲) とりあえずroot(=6)を積む。 | 6 | |
乙) さっそくその6をpopする。 | ||
丁) 右があるので、右(=8)を積む。 | 8 | |
戊) 6を処理済みにして、積む。 | 8 [6] | |
己) 左があるので、左(=4)を積む。 | 8 [6] 4 | |
乙) popして4を得る。 | 8 [6] | |
丁) 右があるので、右(=5)を積む。 | 8 [6] 5 | |
戊) 4を処理済みにして、積む。 | 8 [6] 5 [4] | |
己) 左があるので、左(=1)を積む。 | 8 [6] 5 [4] 1 | |
乙) popして1を得る。 | 8 [6] 5 [4] | |
戊) 1を処理済みにして、積む。 | 8 [6] 5 [4] [1] | |
乙) popして[1]を得る。 | 8 [6] 5 [4] | |
丙) [1]は処理済みなので出力する。 | 8 [6] 5 [4] | 1 |
乙) popして[4]を得る。 | 8 [6] 5 | 1 |
丙) [4]は処理済みなので出力する。 | 8 [6] 5 | 1 4 |
乙) popして5を得る。 | 8 [6] | 1 4 |
戊) 5を処理済みにして、積む。 | 8 [6] [5] | 1 4 |
乙) popして[5]を得る。 | 8 [6] | 1 4 |
丙) [5]は処理済みなので出力する。 | 8 [6] | 1 4 5 |
乙) popして[6]を得る。 | 8 | 1 4 5 |
丙) [6]は処理済みなので出力する。 | 8 | 1 4 5 6 |
まぁ、あとは繰り返しなので略。
ちゃんとtraverseと同じ順になってると思います。
とりあえず文章読むよりはstackの遷移を眺めるといいかも。
んー、他にいい方法ないかねぇ...。
課題83
続いてqsort。
これはキューを使えばおっけー。
前にやったqsortを理解できた人は苦ではないはず。
逆に言えばqsortを理解できなかった人はこれもきついかも。
とりあえず、「ソートする範囲」を一つの構造体にして、その構造体のキューを作るといい感じ。
「ソートする範囲」の中からピボットを拾ってきて、それをもとに、「小さいの」と「大きいの」にわけてそれぞれの範囲を構造体に打ち込んでキューにいれる。
あとは、ループ入る前に、配列の全範囲をキューに入れてあげて、ループ先頭ではキューからとる、という作業をしてやればおっけー。
あ、スタックでもいいのか。
なんか全体的に簡素なのはうちのモチベーションが低いからとか、そういうのじゃないですよ。
えぇ、そうですとも。