UNPKG

@rimbu/graph

Version:

Immutable Graph data structures for TypeScript

121 lines 5.24 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.traverseDepthFirstCustom = traverseDepthFirstCustom; exports.traverseDepthFirstHashed = traverseDepthFirstHashed; exports.traverseDepthFirstSorted = traverseDepthFirstSorted; var tslib_1 = require("tslib"); var common_1 = require("@rimbu/common"); var hashed_1 = require("@rimbu/hashed"); var sorted_1 = require("@rimbu/sorted"); var stream_1 = require("@rimbu/stream"); var custom_1 = require("@rimbu/stream/custom"); var GraphDepthFirstStream = /** @class */ (function (_super) { tslib_1.__extends(GraphDepthFirstStream, _super); function GraphDepthFirstStream(node, graph, addVisitedNode) { var _this = _super.call(this) || this; _this.node = node; _this.graph = graph; _this.addVisitedNode = addVisitedNode; return _this; } GraphDepthFirstStream.prototype[Symbol.iterator] = function () { return new GraphDepthFirstIterable(this.node, this.graph, this.addVisitedNode); }; return GraphDepthFirstStream; }(custom_1.StreamBase)); var GraphDepthFirstIterable = /** @class */ (function (_super) { tslib_1.__extends(GraphDepthFirstIterable, _super); function GraphDepthFirstIterable(node, graph, addVisitedNode, isRoot) { if (isRoot === void 0) { isRoot = true; } var _this = _super.call(this) || this; _this.node = node; _this.graph = graph; _this.addVisitedNode = addVisitedNode; if (isRoot) _this.addVisitedNode(node); var startConnectionStream = _this.graph.getConnectionStreamFrom(_this.node); _this.arrowIterator = startConnectionStream[Symbol.iterator](); return _this; } GraphDepthFirstIterable.prototype.fastNext = function (otherwise) { if (this.currentIterator) { var nextNode = this.currentIterator.fastNext(); if (undefined !== nextNode) return nextNode; } var nextConnection; while (undefined !== (nextConnection = this.arrowIterator.fastNext())) { var result = nextConnection; var targetNode = result[1]; if (this.addVisitedNode(targetNode)) { this.currentIterator = new GraphDepthFirstIterable(targetNode, this.graph, this.addVisitedNode, false); return result; } } return (0, common_1.OptLazy)(otherwise); }; return GraphDepthFirstIterable; }(custom_1.FastIteratorBase)); /** * Returns a stream of connections that can be reached in the given `graph` * starting at the given `startNode`, and using depth-first traversal. It can * avoid loops if needed in a custom way by supplying the `addVisitedNode` function. * @param graph - the graph to traverse * @param startNode - the start node within the graph * @param addVisitedNode - a function taking the currenty traversed node, * and returning true if the node has been traversed before, or false otherwise * @example * ```ts * const g = EdgeGraphHashed.of([1, 2], [2, 3], [1, 3], [3, 4]) * const stream = traverseDepthFirstCustom(g, 1) * console.log(stream.toArray()) * // => [[1, 2], [2, 3], [1, 3], [3, 4]] * ``` */ function traverseDepthFirstCustom(graph, startNode, addVisitedNode) { if (addVisitedNode === void 0) { addVisitedNode = function () { return true; }; } if (!graph.nonEmpty() || !graph.hasNode(startNode)) return stream_1.Stream.empty(); return new GraphDepthFirstStream(startNode, graph, addVisitedNode); } /** * Returns a stream of connections that can be reached in the given `graph` * starting at the given `startNode`, and using depth-first traversal. It avoids * loops by internally placing the visited nodes in a HashSet builder. * @param graph - the graph to traverse * @param startNode - the start node within the graph * @example * ```ts * const g = EdgeGraphHashed.of([1, 2], [2, 3], [1, 3], [3, 4]) * const stream = traverseDepthFirstHashed(g, 1) * console.log(stream.toArray()) * // => [[1, 2], [2, 3], [1, 3], [3, 4]] * ``` */ function traverseDepthFirstHashed(graph, startNode) { if (!graph.nonEmpty() || !graph.hasNode(startNode)) return stream_1.Stream.empty(); var visitSet = hashed_1.HashSet.builder(); return new GraphDepthFirstStream(startNode, graph, visitSet.add); } /** * Returns a stream of connections that can be reached in the given `graph` * starting at the given `startNode`, and using depth-first traversal. It avoids * loops by internally placing the visited nodes in a SortedSet builder. * @param graph - the graph to traverse * @param startNode - the start node within the graph * @example * ```ts * const g = EdgeGraphHashed.of([1, 2], [2, 3], [1, 3], [3, 4]) * const stream = traverseDepthFirstSorted(g, 1) * console.log(stream.toArray()) * // => [[1, 2], [2, 3], [1, 3], [3, 4]] * ``` */ function traverseDepthFirstSorted(graph, startNode) { if (!graph.nonEmpty() || !graph.hasNode(startNode)) return stream_1.Stream.empty(); var visitSet = sorted_1.SortedSet.builder(); return new GraphDepthFirstStream(startNode, graph, visitSet.add); } //# sourceMappingURL=traverse-depth-first.cjs.map