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;
|
|
};
|
|
}
|
|
```
|