6.3 KiB
id, title, challengeType, forumTopicId, dashedName
| id | title | challengeType | forumTopicId | dashedName |
|---|---|---|---|---|
| 587d825c367417b2b2512c90 | Búsqueda en Anchura | 1 | 301622 | breadth-first-search |
--description--
Hasta ahora, hemos aprendido diferentes formas de crear representaciones de grafos. ¿Y ahora qué? Una pregunta natural a tener es ¿cuál es la distancia entre dos cualquiera en el grafo? Introduciremos los algoritmos de recorrido de grafos.
Los Algoritmos de Recorrido son algoritmos para atravesar o visitar los nodos en un grafo. Un tipo de algoritmo de recorrido es el algoritmo de búsqueda en anchura.
Este algoritmo empieza en un nodo y visita todos los vecinos que están a una arista de distancia. Luego visita cada uno de los vecinos hasta que todos los nodos hayan sido visitados.
Una estructura de datos importante que ayudará a implementar el algoritmo de búsqueda en anchura es la cola. Esta es un arreglo donde tu puedes agregar elementos en un extremos y eliminarlos desde el otro extremo. Esta también es conocida como una estructura de datos FIFO o First-In-First-Out.
Visualmente, esto es lo que el algoritmo hace.
El sombreado gris representa un nodo siendo agregado a la cola y el sombreado negro representa un nodo siendo removido de la cola. Ve como cada vez un nodo se elimina de la cola (el nodo se vuelve negro), todos los vecinos son agregados en la cola ( los nodos se vuelven gris).
Para implementar este algoritmo, necesitarás un estructura de grafo y un nodo en el que quieras comenzar.
Primero, querrá ser consciente de las distancias desde, o números de aristas de distancias, el nodo inicial. Querrás empezar todas las distancias con un número largo como el Infinity. Esto evita que existan problemas cuando un nodo no puede ser alcanzado desde el nodo inicial. Luego, querrás ir desde el nodo inicial a sus vecinos. Estos vecinos estan a una arista de distancia y en este punto debes agregar una unidad de distancia a las distancia que has estado guardando.
--instructions--
Escribe una función bfs() que tome una matriz de adyacencia de un grafo ( un arreglo de dos-dimensiones) y una etiqueta para el nodo raíz como parámetro. La etiqueta del nodo solo debe ser el valor entero del nodo entre 0 y n - 1, donde n es el total de números de nodos en el grafo.
Tu función mostrará pares clave-valor como un objeto JavaScript con el nodo y su distancia desde la raíz. Si el nodo no puede ser alcanzado, deberá tener una distancia de Infinity.
--hints--
El grafo de entrada [[0, 1, 0, 0], [1, 0, 1, 0], [0, 1, 0, 1], [0, 0, 1, 0]] con un nodo inicial 1 debe devolver {0: 1, 1: 0, 2: 1, 3: 2}
assert(
(function () {
var graph = [
[0, 1, 0, 0],
[1, 0, 1, 0],
[0, 1, 0, 1],
[0, 0, 1, 0]
];
var results = bfs(graph, 1);
return isEquivalent(results, { 0: 1, 1: 0, 2: 1, 3: 2 });
})()
);
El grafo de entrada [[0, 1, 0, 0], [1, 0, 1, 0], [0, 1, 0, 0], [0, 0, 0, 0]] con un nodo inicial 1 debe devolver {0: 1, 1: 0, 2: 1, 3: Infinity}
assert(
(function () {
var graph = [
[0, 1, 0, 0],
[1, 0, 1, 0],
[0, 1, 0, 0],
[0, 0, 0, 0]
];
var results = bfs(graph, 1);
return isEquivalent(results, { 0: 1, 1: 0, 2: 1, 3: Infinity });
})()
);
El grafo de entrada [[0, 1, 0, 0], [1, 0, 1, 0], [0, 1, 0, 1], [0, 0, 1, 0]] con un nodo inicial 0 debe devolver {0: 0, 1: 1, 2: 2, 3: 3}
assert(
(function () {
var graph = [
[0, 1, 0, 0],
[1, 0, 1, 0],
[0, 1, 0, 1],
[0, 0, 1, 0]
];
var results = bfs(graph, 0);
return isEquivalent(results, { 0: 0, 1: 1, 2: 2, 3: 3 });
})()
);
El grafo de entrada [[0, 1], [1, 0]] con un nodo inicial 0 debe devolver {0: 0, 1: 1}
assert(
(function () {
var graph = [
[0, 1],
[1, 0]
];
var results = bfs(graph, 0);
return isEquivalent(results, { 0: 0, 1: 1 });
})()
);
--seed--
--after-user-code--
// Source: http://adripofjavascript.com/blog/drips/object-equality-in-javascript.html
function isEquivalent(a, b) {
// Create arrays of property names
var aProps = Object.getOwnPropertyNames(a);
var bProps = Object.getOwnPropertyNames(b);
// If number of properties is different,
// objects are not equivalent
if (aProps.length != bProps.length) {
return false;
}
for (var i = 0; i < aProps.length; i++) {
var propName = aProps[i];
// If values of same property are not equal,
// objects are not equivalent
if (a[propName] !== b[propName]) {
return false;
}
}
// If we made it this far, objects
// are considered equivalent
return true;
}
--seed-contents--
function bfs(graph, root) {
var nodesLen = {};
return nodesLen;
};
var exBFSGraph = [
[0, 1, 0, 0],
[1, 0, 1, 0],
[0, 1, 0, 1],
[0, 0, 1, 0]
];
console.log(bfs(exBFSGraph, 3));
--solutions--
function bfs(graph, root) {
var nodesLen = {};
// Set all distances to infinity
for (var i = 0; i < graph.length; i++) {
nodesLen[i] = Infinity;
}
nodesLen[root] = 0; // ...except root node
var queue = [root]; // Keep track of nodes to visit
var current; // Current node traversing
// Keep on going until no more nodes to traverse
while (queue.length !== 0) {
current = queue.shift();
// Get adjacent nodes from current node
var curConnected = graph[current]; // Get layer of edges from current
var neighborIdx = []; // List of nodes with edges
var idx = curConnected.indexOf(1); // Get first edge connection
while (idx !== -1) {
neighborIdx.push(idx); // Add to list of neighbors
idx = curConnected.indexOf(1, idx + 1); // Keep on searching
}
// Loop through neighbors and get lengths
for (var j = 0; j < neighborIdx.length; j++) {
// Increment distance for nodes traversed
if (nodesLen[neighborIdx[j]] === Infinity) {
nodesLen[neighborIdx[j]] = nodesLen[current] + 1;
queue.push(neighborIdx[j]); // Add new neighbors to queue
}
}
}
return nodesLen;
}