--- id: 587d8257367417b2b2512c7e title: Використання пошуку в глибину у двійковому дереві пошуку challengeType: 1 forumTopicId: 301719 dashedName: use-depth-first-search-in-a-binary-search-tree --- # --description-- Нам уже відомо, як у двійковому дереві пошуку знайти певне значення. А якщо ми хочемо обійти дерево повністю? Або якщо нам потрібно просто знайти якесь значення, але при цьому ми не маємо впорядкованого дерева? Саме тому ми познайомимо вас з деякими методами обходу дерева, які використовуються для дослідження деревоподібних структур даних. Спершу розглянемо пошук у глибину. Цей метод дозволяє дослідити дане піддерево настільки глибоко, наскільки це можливо, перед тим, як продовжити пошук на іншому піддереві. Пошук може здійснюватися трьома різними способами. Серединний порядок (inorder): з крайнього лівого вузла до крайнього правого вузла. Прямий порядок (pre-order): обхід всіх кореневих, а потім листових вузлів. Зворотний порядок (post-order): обхід всіх листових, а потім кореневих вузлів. Нескладно здогадатися, що можна обирати різні пошукові методи залежно від того, які дані зберігає дерево і що ви шукаєте. Для двійкового дерева пошуку серединний обхід повертає вузли у сортованому порядку. # --instructions-- Створімо в нашому двійковому дереві пошуку вищезгадані три методи. Пошук у глибину має за основу рекурсивну операцію, яка продовжує досліджувати наступні піддерева за умови, що є дочірні вузли. Коли ви зрозумієте основні поняття, то зможете легко змінювати порядок обходу вузлів та піддерев, щоб реалізувати будь-який з вищезгаданих пошуків. До прикладу, під час зворотного пошуку ми захотіли б рекурсувати весь шлях до листового вузла перед тим, як повернути всі вузли. А під час прямого пошуку ми б хотіли спочатку повернути вузли, а тоді продовжити обходити дерево далі вниз. Визначте в нашому дереві методи `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; }; } ```