329 lines
		
	
	
		
			8.8 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
			
		
		
	
	
			329 lines
		
	
	
		
			8.8 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
| ---
 | |
| id: 587d8257367417b2b2512c7e
 | |
| title: 二分探索木で深さ優先探索を使用する
 | |
| challengeType: 1
 | |
| forumTopicId: 301719
 | |
| dashedName: use-depth-first-search-in-a-binary-search-tree
 | |
| ---
 | |
| 
 | |
| # --description--
 | |
| 
 | |
| 二分探索木で特定の値を検索する方法は既に学びました。 しかし、木全体を探索したい場合はどうすれば良いでしょうか? あるいは、順序付きの木がないときに、単に値を検索したい場合はどうでしょうか? ここでは、ツリーデータ構造を探索するために木を走査する方法をいくつか紹介します。 1 つ目は深さ優先探索です。 深さ優先探索は、探索が別の部分木に移る前に、与えられた部分木をできるだけ深く探索します。 これを行うには次の 3 つの方法があります。通りがけ順: 左端のノードで探索を開始し、右端のノードで終了します。 行きがけ順: 葉より先にすべての根を探索します。 帰りがけ順: 根より先にすべての葉を探索します。 お察しの通り、木がどのような種類のデータを格納しているか、そして何を探したいかに応じて、異なる検索方法を選択できます。 二分探索木の場合、通りがけ順走査は、ソートされた順序でノードを返します。
 | |
| 
 | |
| # --instructions--
 | |
| 
 | |
| ここでは、二分探索木に対してこれら 3 つの探索方法を作成します。 深さ優先探索は、子ノードが存在する限りさらに部分木の探索を続けるという、本質的に再帰性を持つ操作です。 この基本概念を理解したら、ノードと部分木の探索順序を変えるだけで上述の 3 つの探索をすべて作成できます。 例えば帰りがけ順の探索では、ノード自体を返し始める前に、葉ノードまでの全体を再帰的に探索します。一方、行きがけ順の探索では、最初にノードを返してから、木の下の方へ再帰的に探索し続けます。 この木に `inorder`、`preorder`、`postorder` の各メソッドを定義してください。 これらの各メソッドは、木の走査を表す要素の配列を返す必要があります。 ノード自体ではなく、配列内の各ノードの整数値を返すようにしてください。 最後に、木が空の場合は `null` を返してください。
 | |
| 
 | |
| # --hints--
 | |
| 
 | |
| `BinarySearchTree` データ構造が存在する必要があります。
 | |
| 
 | |
| ```js
 | |
| assert(
 | |
|   (function () {
 | |
|     var test = false;
 | |
|     if (typeof BinarySearchTree !== 'undefined') {
 | |
|       test = new BinarySearchTree();
 | |
|     }
 | |
|     return typeof test == 'object';
 | |
|   })()
 | |
| );
 | |
| ```
 | |
| 
 | |
| 二分探索木に `inorder` というメソッドが必要です。
 | |
| 
 | |
| ```js
 | |
| assert(
 | |
|   (function () {
 | |
|     var test = false;
 | |
|     if (typeof BinarySearchTree !== 'undefined') {
 | |
|       test = new BinarySearchTree();
 | |
|     } else {
 | |
|       return false;
 | |
|     }
 | |
|     return typeof test.inorder == 'function';
 | |
|   })()
 | |
| );
 | |
| ```
 | |
| 
 | |
| 二分探索木に `preorder` というメソッドが必要です。
 | |
| 
 | |
| ```js
 | |
| assert(
 | |
|   (function () {
 | |
|     var test = false;
 | |
|     if (typeof BinarySearchTree !== 'undefined') {
 | |
|       test = new BinarySearchTree();
 | |
|     } else {
 | |
|       return false;
 | |
|     }
 | |
|     return typeof test.preorder == 'function';
 | |
|   })()
 | |
| );
 | |
| ```
 | |
| 
 | |
| 二分探索木に `postorder` というメソッドが必要です。
 | |
| 
 | |
| ```js
 | |
| assert(
 | |
|   (function () {
 | |
|     var test = false;
 | |
|     if (typeof BinarySearchTree !== 'undefined') {
 | |
|       test = new BinarySearchTree();
 | |
|     } else {
 | |
|       return false;
 | |
|     }
 | |
|     return typeof test.postorder == 'function';
 | |
|   })()
 | |
| );
 | |
| ```
 | |
| 
 | |
| `inorder` メソッドは、通りがけ順走査によって得たノード値の配列を返す必要があります。
 | |
| 
 | |
| ```js
 | |
| assert(
 | |
|   (function () {
 | |
|     var test = false;
 | |
|     if (typeof BinarySearchTree !== 'undefined') {
 | |
|       test = new BinarySearchTree();
 | |
|     } else {
 | |
|       return false;
 | |
|     }
 | |
|     if (typeof test.inorder !== 'function') {
 | |
|       return false;
 | |
|     }
 | |
|     test.add(7);
 | |
|     test.add(1);
 | |
|     test.add(9);
 | |
|     test.add(0);
 | |
|     test.add(3);
 | |
|     test.add(8);
 | |
|     test.add(10);
 | |
|     test.add(2);
 | |
|     test.add(5);
 | |
|     test.add(4);
 | |
|     test.add(6);
 | |
|     return test.inorder().join('') == '012345678910';
 | |
|   })()
 | |
| );
 | |
| ```
 | |
| 
 | |
| `preorder` メソッドは、行きがけ順走査によって得たノード値の配列を返す必要があります。
 | |
| 
 | |
| ```js
 | |
| assert(
 | |
|   (function () {
 | |
|     var test = false;
 | |
|     if (typeof BinarySearchTree !== 'undefined') {
 | |
|       test = new BinarySearchTree();
 | |
|     } else {
 | |
|       return false;
 | |
|     }
 | |
|     if (typeof test.preorder !== 'function') {
 | |
|       return false;
 | |
|     }
 | |
|     test.add(7);
 | |
|     test.add(1);
 | |
|     test.add(9);
 | |
|     test.add(0);
 | |
|     test.add(3);
 | |
|     test.add(8);
 | |
|     test.add(10);
 | |
|     test.add(2);
 | |
|     test.add(5);
 | |
|     test.add(4);
 | |
|     test.add(6);
 | |
|     return test.preorder().join('') == '710325469810';
 | |
|   })()
 | |
| );
 | |
| ```
 | |
| 
 | |
| `postorder` メソッドは、帰りがけ順走査によって得たノード値の配列を返す必要があります。
 | |
| 
 | |
| ```js
 | |
| assert(
 | |
|   (function () {
 | |
|     var test = false;
 | |
|     if (typeof BinarySearchTree !== 'undefined') {
 | |
|       test = new BinarySearchTree();
 | |
|     } else {
 | |
|       return false;
 | |
|     }
 | |
|     if (typeof test.postorder !== 'function') {
 | |
|       return false;
 | |
|     }
 | |
|     test.add(7);
 | |
|     test.add(1);
 | |
|     test.add(9);
 | |
|     test.add(0);
 | |
|     test.add(3);
 | |
|     test.add(8);
 | |
|     test.add(10);
 | |
|     test.add(2);
 | |
|     test.add(5);
 | |
|     test.add(4);
 | |
|     test.add(6);
 | |
|     return test.postorder().join('') == '024653181097';
 | |
|   })()
 | |
| );
 | |
| ```
 | |
| 
 | |
| `inorder` メソッドは、空の木の場合に `null` を返す必要があります。
 | |
| 
 | |
| ```js
 | |
| assert(
 | |
|   (function () {
 | |
|     var test = false;
 | |
|     if (typeof BinarySearchTree !== 'undefined') {
 | |
|       test = new BinarySearchTree();
 | |
|     } else {
 | |
|       return false;
 | |
|     }
 | |
|     if (typeof test.inorder !== 'function') {
 | |
|       return false;
 | |
|     }
 | |
|     return test.inorder() == null;
 | |
|   })()
 | |
| );
 | |
| ```
 | |
| 
 | |
| `preorder` メソッドは、空の木の場合に `null` を返す必要があります。
 | |
| 
 | |
| ```js
 | |
| assert(
 | |
|   (function () {
 | |
|     var test = false;
 | |
|     if (typeof BinarySearchTree !== 'undefined') {
 | |
|       test = new BinarySearchTree();
 | |
|     } else {
 | |
|       return false;
 | |
|     }
 | |
|     if (typeof test.preorder !== 'function') {
 | |
|       return false;
 | |
|     }
 | |
|     return test.preorder() == null;
 | |
|   })()
 | |
| );
 | |
| ```
 | |
| 
 | |
| `postorder` メソッドは、空の木の場合に `null` を返す必要があります。
 | |
| 
 | |
| ```js
 | |
| assert(
 | |
|   (function () {
 | |
|     var test = false;
 | |
|     if (typeof BinarySearchTree !== 'undefined') {
 | |
|       test = new BinarySearchTree();
 | |
|     } else {
 | |
|       return false;
 | |
|     }
 | |
|     if (typeof test.postorder !== 'function') {
 | |
|       return false;
 | |
|     }
 | |
|     return test.postorder() == null;
 | |
|   })()
 | |
| );
 | |
| ```
 | |
| 
 | |
| # --seed--
 | |
| 
 | |
| ## --after-user-code--
 | |
| 
 | |
| ```js
 | |
| BinarySearchTree.prototype = Object.assign(
 | |
|   BinarySearchTree.prototype,
 | |
|   {
 | |
|     add: function(value) {
 | |
|       function searchTree(node) {
 | |
|         if (value < node.value) {
 | |
|           if (node.left == null) {
 | |
|             node.left = new Node(value);
 | |
|             return;
 | |
|           } else if (node.left != null) {
 | |
|             return searchTree(node.left);
 | |
|           }
 | |
|         } else if (value > node.value) {
 | |
|           if (node.right == null) {
 | |
|             node.right = new Node(value);
 | |
|             return;
 | |
|           } else if (node.right != null) {
 | |
|             return searchTree(node.right);
 | |
|           }
 | |
|         } else {
 | |
|           return null;
 | |
|         }
 | |
|       }
 | |
| 
 | |
|       var node = this.root;
 | |
|       if (node == null) {
 | |
|         this.root = new Node(value);
 | |
|         return;
 | |
|       } else {
 | |
|         return searchTree(node);
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| );
 | |
| ```
 | |
| 
 | |
| ## --seed-contents--
 | |
| 
 | |
| ```js
 | |
| var displayTree = tree => console.log(JSON.stringify(tree, null, 2));
 | |
| function Node(value) {
 | |
|   this.value = value;
 | |
|   this.left = null;
 | |
|   this.right = null;
 | |
| }
 | |
| function BinarySearchTree() {
 | |
|   this.root = null;
 | |
|   // Only change code below this line
 | |
| 
 | |
|   // Only change code above this line
 | |
| }
 | |
| ```
 | |
| 
 | |
| # --solutions--
 | |
| 
 | |
| ```js
 | |
| var displayTree = tree => console.log(JSON.stringify(tree, null, 2));
 | |
| function Node(value) {
 | |
|   this.value = value;
 | |
|   this.left = null;
 | |
|   this.right = null;
 | |
| }
 | |
| function BinarySearchTree() {
 | |
|   this.root = null;
 | |
|   this.result = [];
 | |
| 
 | |
|   this.inorder = function(node) {
 | |
|     if (!node) node = this.root;
 | |
|     if (!node) return null;
 | |
| 
 | |
|     if (node.left) this.inorder(node.left);
 | |
|     this.result.push(node.value);
 | |
|     if (node.right) this.inorder(node.right);
 | |
|     return this.result;
 | |
|   };
 | |
|   this.preorder = function(node) {
 | |
|     if (!node) node = this.root;
 | |
|     if (!node) return null;
 | |
| 
 | |
|     this.result.push(node.value);
 | |
|     if (node.left) this.preorder(node.left);
 | |
|     if (node.right) this.preorder(node.right);
 | |
|     return this.result;
 | |
|   };
 | |
|   this.postorder = function(node) {
 | |
|     if (!node) node = this.root;
 | |
|     if (!node) return null;
 | |
| 
 | |
|     if (node.left) this.postorder(node.left);
 | |
|     if (node.right) this.postorder(node.right);
 | |
|     this.result.push(node.value);
 | |
| 
 | |
|     return this.result;
 | |
|   };
 | |
| }
 | |
| ```
 |