Files
freeCodeCamp/curriculum/challenges/ukrainian/10-coding-interview-prep/data-structures/depth-first-search.md
2024-06-11 19:02:29 +02:00

226 lines
7.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
id: 587d825d367417b2b2512c96
title: Пошук у глибину
challengeType: 1
forumTopicId: 301640
dashedName: depth-first-search
---
# --description--
У цьому завданні ознайомимось з алгоритмом обходу графа під назвою <dfn>пошук у глибину</dfn>, який схожий до <dfn>пошуку у ширину</dfn>.
Під час пошуку в ширину алгоритм починається з вихідної вершини, а далі проходить вершини таким чином, що кожне наступне ребро є довшим за попереднє. В той час алгоритм <dfn>пошуку в глибину</dfn> спочатку обирає найдовше ребро.
Коли алгоритм досягне кінця шляху, він повернеться до останньої вершини з невідвіданим ребром і продовжить пошук.
На анімації нижче наочно показано, яким чином працює цей алгоритм. Алгоритм починається з верхньої вершини і проходить по вершинах так, як пронумеровано на анімації.
<img class='img-responsive' alt="" src='https://camo.githubusercontent.com/aaad9e39961daf34d967c616edeb50abf3bf1235/68747470733a2f2f75706c6f61642e77696b696d656469612e6f72672f77696b6970656469612f636f6d6d6f6e732f372f37662f44657074682d46697273742d5365617263682e676966' />
Зверніть увагу: щоразу, коли цей алгоритм відвідує якусь вершину, він не проходить всіх сусідів (на відміну від пошуку в ширину). Натомість він спочатку відвідує одну з сусідніх вершин і далі проходить вниз, допоки не відвідає всі вершини на цьому шляху.
Для реалізації цього алгоритму потрібно використати стек. Стек — це масив, де останній доданий елемент видаляється першим. Ця структура також відома як <dfn>останнім прийшло — першим пішло</dfn>. Стек допоможе при пошуку в глибину, адже (коли ми додаємо до стеку сусідні елементи) спочатку нам потрібно відвідати останніх доданих сусідів і вилучити їх зі стеку.
В простому випадку цей алгоритм виводить список вершин, доступних з даної вершини. Тому також потрібно відстежувати відвідані вершини.
# --instructions--
Напишіть функцію `dfs()`, яка приймає неорієнтований граф матриці суміжності (`graph`) та мітку кореневої вершини (`root`) як параметри. Міткою вершини буде ціле значення вершини між `0` та `n - 1`, де `n` — загальна кількість вершин графа.
Функція має вивести масив усіх вершин, які можна досягти з кореня (`root`).
# --hints--
Вхідний граф `[[0, 1, 0, 0], [1, 0, 1, 0], [0, 1, 0, 1], [0, 0, 1, 0]]` з початковою вершиною `1` має повернути масив, який містить `0`, `1`, `2` та `3`.
```js
assert.sameMembers(
(function () {
var graph = [
[0, 1, 0, 0],
[1, 0, 1, 0],
[0, 1, 0, 1],
[0, 0, 1, 0]
];
return dfs(graph, 1);
})(),
[0, 1, 2, 3]
);
```
Вхідний граф `[[0, 1, 0, 0], [1, 0, 1, 0], [0, 1, 0, 1], [0, 0, 1, 0]]` з початковою вершиною `3` має повернути масив, який містить `3`, `2`, `1` та `0`.
```js
assert.sameMembers(
(function () {
var graph = [
[0, 1, 0, 0],
[1, 0, 1, 0],
[0, 1, 0, 1],
[0, 0, 1, 0]
];
return dfs(graph, 3);
})(),
[3, 2, 1, 0]
);
```
Вхідний граф `[[0, 1, 0, 0], [1, 0, 1, 0], [0, 1, 0, 1], [0, 0, 1, 0]]` з початковою вершиною `1` має повернути масив з чотирма елементами.
```js
assert(
(function () {
var graph = [
[0, 1, 0, 0],
[1, 0, 1, 0],
[0, 1, 0, 1],
[0, 0, 1, 0]
];
return dfs(graph, 1);
})().length === 4
);
```
Вхідний граф `[[0, 1, 0, 0], [1, 0, 1, 0], [0, 1, 0, 0], [0, 0, 0, 0]]` з початковою вершиною `3` має повернути масив, який містить `3`.
```js
assert.sameMembers(
(function () {
var graph = [
[0, 1, 0, 0],
[1, 0, 1, 0],
[0, 1, 0, 0],
[0, 0, 0, 0]
];
return dfs(graph, 3);
})(),
[3]
);
```
Вхідний граф `[[0, 1, 0, 0], [1, 0, 1, 0], [0, 1, 0, 0], [0, 0, 0, 0]]` з початковою вершиною `3` має повернути масив з одним елементом.
```js
assert(
(function () {
var graph = [
[0, 1, 0, 0],
[1, 0, 1, 0],
[0, 1, 0, 0],
[0, 0, 0, 0]
];
return dfs(graph, 3);
})().length === 1
);
```
Вхідний граф `[[0, 1, 0, 0], [1, 0, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0]]` з початковою вершиною `3` має повернути масив, який містить `2` та `3`.
```js
assert.sameMembers(
(function () {
var graph = [
[0, 1, 0, 0],
[1, 0, 0, 0],
[0, 0, 0, 1],
[0, 0, 1, 0]
];
return dfs(graph, 3);
})(),
[2, 3]
);
```
Вхідний граф `[[0, 1, 0, 0], [1, 0, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0]]` з початковою вершиною `3` має повернути масив з двома елементами.
```js
assert(
(function () {
var graph = [
[0, 1, 0, 0],
[1, 0, 0, 0],
[0, 0, 0, 1],
[0, 0, 1, 0]
];
return dfs(graph, 3);
})().length === 2
);
```
Вхідний граф `[[0, 1, 0, 0], [1, 0, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0]]` з початковою вершиною `0` має повернути масив, який містить `0` та `1`.
```js
assert.sameMembers(
(function () {
var graph = [
[0, 1, 0, 0],
[1, 0, 0, 0],
[0, 0, 0, 1],
[0, 0, 1, 0]
];
return dfs(graph, 0);
})(),
[0, 1]
);
```
Вхідний граф `[[0, 1, 0, 0], [1, 0, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0]]` з початковою вершиною `0` має повернути масив з двома елементами.
```js
assert(
(function () {
var graph = [
[0, 1, 0, 0],
[1, 0, 0, 0],
[0, 0, 0, 1],
[0, 0, 1, 0]
];
return dfs(graph, 0);
})().length === 2
);
```
# --seed--
## --seed-contents--
```js
function dfs(graph, root) {
}
var exDFSGraph = [
[0, 1, 0, 0],
[1, 0, 1, 0],
[0, 1, 0, 1],
[0, 0, 1, 0]
];
console.log(dfs(exDFSGraph, 3));
```
# --solutions--
```js
function dfs(graph, root) {
var stack = [];
var tempV;
var visited = [];
var tempVNeighbors = [];
stack.push(root);
while (stack.length > 0) {
tempV = stack.pop();
if (visited.indexOf(tempV) == -1) {
visited.push(tempV);
tempVNeighbors = graph[tempV];
for (var i = 0; i < tempVNeighbors.length; i++) {
if (tempVNeighbors[i] == 1) {
stack.push(i);
}
}
}
}
return visited;
}
```