More Related Content
More from Hiromu Shioya (20)
慣れない言語で車輪の再発明をしよう〜JavaScriptでツリーソート編〜
- 2. とりあえず自己紹介
• katsumic(読みは”かつみっく”で!)
• 職業
• WEB系のプログラマーしてます
• 趣味
• スキー
• キャンプとかアウトドアなもの
• 音楽(ライブ観たりとか)
• 職業がインドアな反動か野外を好む
- 3. 今回の発表に至るいきさつ
• 当勉強会の前身である社内勉強会で、アルゴリズムとデ
ータ構造を扱った回がありました。
• そこから自分が不得意な言語でソートアルゴリズムを実
装しようという宿題が出たんです。
• 私の担当は表題の通り、ツリーソートをJavaScriptで実装
する事。
• ぎゃーJavaScriptちゃんとやった事ねー!!!
• で、ちょっとがんばってみたわけですね。
- 4. JavaScriptについて
• 1995年にNetscape Communications社が開発したプロト
タイプベースのオブジェクト指向型プログラミング言語。
• プロトタイプベース?
• それはまた後ほど!
• 主にWEBアプリケーションがクライアントサイド(WEBブラ
ウザ上)で処理を行う為に利用されている。近年はAjax
のおかげで大活躍してる。
• Ecma Internationalという国際標準化団体によって、
「ECMAScript」として標準化された。
• そのおかげで様々なブラウザがサポート。
- 6. プロトタイプベースについて
• 新しいオブジェクトを作るのに、(クラスではなく)「既に存
在しているオブジェクトのプロトタイプ」をベースにする。
• これに対してJavaやC++のように、クラスにメンバとそれ
を操作する為のメソッドを定義し、そのクラスからインスタ
ンスを生成するプログラミング言語を「クラスベース」のオ
ブジェクト指向言語と言う。
- 7. プロトタイプベースについて
• 具体的に新しいオブジェクトを作るには?
• コンストラクタを使用する。
• function SimpleConstructor() {
• this.data = null;
• }
• var obj = new SimpleConstructor();
•
• 一見、「SimpleConstructor」という名前の関数を定
義しているように見えるが、「SimpleConstructor」オブ
ジェクトのコンストラクタを定義している。
- 8. プロトタイプベースについて
• prototypeプロパティ
• どのオブジェクトも暗黙に持っているプロパティ。
• 何かのオブジェクトの機能拡張を行いたい場合、このprototypeに新たな
オブジェクト(プロパティ、メソッド)を追加する事で行える。
• 例えばArrayオブジェクトに配列の内容をカンマ区切りで表示するメソッド
を追加したい場合。
• Array.prototype.toString = function() {
• var str = quot;quot;;
• for (var i = 0; i < this.length; i++) {
• if (i != 0) { str += quot;,quot;; }
• str += this[i];
• }
• return quot;[quot; + str + quot;]quot;;
• }
- 9. プロトタイプベースについて
• 既存のオブジェクトから継承して作りたい場合
• 例・Stringクラスを継承したStringListクラスを作る
• function StringList() {}; // コンストラクタを定義
• StringList.prototype = new String(); // Stringを継承
•
• 前ページに出てきたprototypeプロパティに継承したい
オブジェクトのコピーを渡す事で継承する事ができる。
• もしStringオブジェクトを機能拡張すれば、期待
通り StringListオブジェクトにも反映される。
- 10. プロトタイプベースについて
• クラスベース
• データ構造も含めてかっちりとした設計がある場合に
はこちらの方が向いている。
• プロトタイプベース
• 実現したい機能を中心に実装していくのに向いている。
• ・・・というのが今のところの認識。多分もっと深い意味が
あるのだろうと思いますが。
• 誤解してたら優しく突っ込んでください。
正直まだまだ理解が足りてないですがこんな所で
- 11. JavaScriptについて
• その他
• 詳しく調べてないですがブラウザ以外(サーバーサイ
ド)で利用しようというプロジェクトも幾つかあるようで
す(Rhino、Aptana Jaxerなど)。
• WSH(Windows Script Host)でも利用可能(でもそれ
はJScriptという方言ですね!)。
• この辺は蛇足でしたm(_ _)m
- 13. ツリーソートについて
• 木構造の一種である、「二分探索木」の特性を利用して
整列させるアルゴリズム。
• バイナリツリーソート、二分木ソートなどとも。
• ソートのアルゴリズムというより、 二分探索木 を「作っ
て」それを「なぞる(走査する)」事が実装としてはメインと
言った方が良い。
• そのせいか「ツリーソート」って名前はググってもあん
まりでてきません。Wikipediaでも英語版で検索しないと
出てこない…。
- 14. 木構造について
• データの階層(親子)関係を表現するためのデータ構造。
• 値を持つ「ノード(節)」で構成される。
• ノードの中には1つだけ「ルート(根)」というノードがある。
図にした場合、一般的に一番上に書く。
• 2つのつながっているノードを見たとき、ルートに近い方
を「親ノード」、ルートから遠い方を「子ノード」と言う。
• 各ノードの親ノードは1つだけしかありえない。だが子ノー
ドは複数ある場合もある。1つの場合もあれば、1つもな
い場合もある。
- 15. 木構造について
• 最も末端のノードを「リーフ(葉)」と呼ぶ。リーフは子ノー
ドを持たない。
• ルートから一番下までの階層の数を「高さ」と呼ぶ。
• あるノードがルートから何階層にあるかを、そのノードの
「深さ」と呼ぶ。
• 木構造の中の一部を切り取ったものを「部分木」と呼ぶ。
まぁ、そんな事言っても図が無いと
イメージわかないですよね
- 16. 木構造について
• 木構造の例
• ○がノード ルート(根)
部分木
高さ
リーフ(葉)
- 17. 二分木について
• ノードが子ノードを最大でも「2つしか持たない」木構造の
事。
• ノードが一つの子ノードを持っているとき、それが左の子
であるか右の子であるかを区別するのが普通の木との
大きな違い。
- 18. 二分木について
• 二分木の図
右
子は最大で
も二つ
左
子ノードが一つでも左右を区別する
- 19. 二分木のなぞり
• いきなり話は変わりますが、二分木を扱うアルゴリズムに
「なぞり(走査)」というものがあります。
• これは木構造の全ノードを体系的に一度ずつ調査する処
理の事を言う。
• なぞりには以下の三種類がある。
• 行きがけ順(前順)のなぞり
• 通りがけ順(間順)のなぞり
• 帰りがけ順(後順)のなぞり
• 「行きがけ」「通りがけ」「帰りがけ」というのは、ルートを
「いつ」調査するかというのを表している。
- 20. 二分木のなぞり
• 行きがけ順(前順)のなぞり
• ルートノードを調査
• 左部分木をなぞって調査(再帰的な処理)
• 右部分木をなぞって調査(再帰的な処理)
- 21. 二分木のなぞり
• 行きがけ順 ①
A
②
B ⑦ C
③
D ④ E ⑧ F
⑤ ⑥ ⑨
G H I
A→B→D→E→G→H→C→F→I の順に調査する
- 22. 二分木のなぞり
• 通りがけ順(間順)のなぞり
• 左部分木をなぞって調査(再帰的な処理)
• ルートノードを調査
• 右部分木をなぞって調査(再帰的な処理)
- 23. 二分木のなぞり
• 通りがけ順 ⑥
A
②
B ⑦ C
①
D ④ E ⑨ F
③ ⑤ ⑧
G H I
D→B→G→E→H→A→C→I→F の順に調査する
- 24. 二分木のなぞり
• 帰りがけ順(後順)のなぞり
• 左部分木をなぞって調査(再帰的な処理)
• 右部分木をなぞって調査(再帰的な処理)
• ルートノードを調査
- 25. 二分木のなぞり
• 帰りがけ順 ⑨
A
⑤
B ⑧ C
①
D ④ E ⑦ F
② ③ ⑥
G H I
D→G→H→E→B→I→F→C→A の順に調査する
- 27. 二分探索木について
• 二分木に違いは無いが、以下の条件が加わる。
• あるノードの左のノードはそのノード「以下の値」を持つ。
• あるノードの右のノードはそのノード「以上の値」を持つ。
• 二分探索木を「通りがけ順」になぞると、その順番に得ら
れる要素がソートされた物になる。
• 今回やりたいのはこれです。
- 28. 二分探索木について
• ノードに値(数値)を持たせて図にすると
8
3 10
1 6 14
4 7 13
- 29. 二分探索木について
• 通りがけ順でなぞる ⑥
8
②
3 ⑦ 10
①
1 ④ 6 ⑨ 14
③ ⑤ ⑧
4 7 13
1→3→4→6→7→8→10→13→14 値の昇順に確かになぞれる!
- 30. 二分探索木について
• 値(ノード)を追加する場合は?
• 前述の以下の条件に則り、
• あるノードの左のノードはそのノード「以下の値」を
持つ。
• あるノードの右のノードはそのノード「以上の値」を
持つ。
• ルートから値を比較して、条件に合致する位置に挿入
する。
• この処理は二分探索木を構築する際にも使用する。
- 32. 実装する
• 要件
• 入力する値は課題として用意された、1〜1000の数値
をランダムに発生させたもの(これを一次元配列に格
納する)。
• それを昇順に並べ替える。
• 大きく二つの処理に分かれる。
• 入力された値から二分探索木を構築する処理。
• 二分探索木を通りがけになぞって、値を取り出す処理。
- 34. 実装してみましたが
• 実はソートに二分探索木を用いる事には問題点がある。
• それは入力データの並びによって木の高さが大きく変動
する事。
• 木の高さが高いほど探索の計算量が増えてしまう。
• なぞりも探索アルゴリズムの一種だから同じく。
• 逆に言うと木の高さが低いほど計算量が少ない。
• 一番低いのは「完全二分木」の状態。
• ルートから全てのリーフまでの深さが等しい二分木を
完全二分木と言う。
- 36. 二分探索木について再び
• 最悪のパターン(入力データが既に昇順ソート済)
• これも二分探索木には違いない・・・
1
2
3
4
5
6
7
- 37. 解決法は?
• 完全二分木が最良のパターンだが、それを維持するの
はコストが高いので、あくまでも「なるべく」バランスを取る
(木の高さを抑える)。
• その高さを抑えるようにした木を「平衡二分探索木」と言
う。
• 高さを維持する為のアルゴリズムを二分探索木に加え
てやれば良いはず。
- 40. 参考・引用資料
• 書籍
「定本Cプログラマのためのアルゴリズムとデータ構造」
近藤嘉雪・著/ソフトバンクパブリッシング・刊
昔々、プログラミングは最初Cで勉強し
たので、この本がアルゴリズムの教本で
した。でも当時は全部は理解できなくて
挫折して、仕事する分には困らなかった
もんで、ずっと埃をかぶってました…。勉
強し直す為に引っ張り出して改めて読ん
でみましたが、とても読み易い文章だと
思います。Cを書く事がなくても概念は
一緒なのでおすすめです。読んだ事は
ありませんが、同じ著者がJavaを対象に
した物も執筆しているようです。
- 41. 参考・引用資料
• 書籍
「初めてのJavaScript」
Shelley Powers・著 武舎広幸、武舎るみ・訳
オライリージャパン・刊
プロトタイプに関する部分を参考にしま
した。内容としては物足りないので次は
同じくオライリーの「JavaScript 第5版」
を読むべきでしょうか。
- 42. 参考・引用資料
• WEBサイト
• http://www.atmarkit.co.jp/fcoding/articles/algorithm/
01/algorithm01a.html
• 「オイシックス株式会社」の山下寛人さんが執筆され
ている@ITの記事。
• ツリーソート(二分探索木の実装)に関する記事は
ありませんが、各種アルゴリズムをJavaScriptを使
った例で説明していたので参考になりました。
• というか表示のさせ方や実行時間計測などはまん
ま使わせて頂きました。
- 43. 感想など
• なんとなくわかったつもりになっていた事の理解を深めら
れて良かったです。こういうのは気持ちいいですよね。
• JavaScriptのプロトタイプベースについてが、「オブジェク
ト指向=クラスベース」な脳みそだったので、一番新鮮&
難解でした。
• 実は最初はほとんどオブジェクト指向じゃない実装をし
ていて、後で学習が進んでから実装しなおしました。
• Firefox上でテストを行っていたのですが、Firebugプラグイ
ンの便利さに感動!