* feat(tools): add seed/solution restore script * chore(curriculum): remove empty sections' markers * chore(curriculum): add seed + solution to Chinese * chore: remove old formatter * fix: update getChallenges parse translated challenges separately, without reference to the source * chore(curriculum): add dashedName to English * chore(curriculum): add dashedName to Chinese * refactor: remove unused challenge property 'name' * fix: relax dashedName requirement * fix: stray tag Remove stray `pre` tag from challenge file. Signed-off-by: nhcarrigan <nhcarrigan@gmail.com> Co-authored-by: nhcarrigan <nhcarrigan@gmail.com>
325 lines
7.7 KiB
Markdown
325 lines
7.7 KiB
Markdown
---
|
||
id: 587d8257367417b2b2512c7e
|
||
title: 在二叉搜索树中使用深度优先搜索
|
||
challengeType: 1
|
||
videoUrl: ''
|
||
dashedName: use-depth-first-search-in-a-binary-search-tree
|
||
---
|
||
|
||
# --description--
|
||
|
||
我们知道如何在二叉搜索树中搜索特定值。但是,如果我们只想探索整棵树呢?或者,如果我们没有有序树,我们只需要搜索一个值?这里我们将介绍一些可用于探索树数据结构的树遍历方法。首先是深度优先搜索。在深度优先搜索中,在搜索继续到另一个子树之前,尽可能深地探索给定子树。有三种方法可以完成:按顺序:从最左边的节点开始搜索,到最右边的节点结束。预购:在树叶前探索所有的根。下订单:在根之前探索所有的叶子。您可能会猜到,您可以选择不同的搜索方法,具体取决于树存储的数据类型以及您要查找的内容。对于二叉搜索树,inorder遍历以排序顺序返回节点。说明:这里我们将在二叉搜索树上创建这三种搜索方法。深度优先搜索是一种固有的递归操作,只要子节点存在,它就会继续探索更多的子树。一旦理解了这个基本概念,您就可以简单地重新排列探索节点和子树的顺序,以生成上述三个搜索中的任何一个。例如,在后序搜索中,我们希望在开始返回任何节点本身之前一直递归到叶节点,而在预订搜索中,我们希望首先返回节点,然后继续递归在树下。在我们的树上定义`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`方法返回由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;
|
||
};
|
||
}
|
||
```
|