UNPKG

pisces-data-structure

Version:

135 lines (95 loc) 4.19 kB
/** * 图结构 */ import type { IVertex, IGraph } from "../../types"; import { SinglyQueue, Stack } from "../index"; class Vertex<T = any> implements IVertex<T> { constructor(public value: T) { } } class Graph<T = any> implements IGraph<T> { private vertices: Vertex<T>[] = []; private adjoinList: WeakMap<Vertex<T>, Vertex<T>[]> = new WeakMap(); private findVertex(value: T): Vertex<T> | null { const _verticesNum = this.vertices.length; for (let _index = 0; _index < _verticesNum; _index++) { const _vertex = this.vertices[_index]; if (_vertex.value === value) { return _vertex; } } return null; } addVertex(value: T) { const _newVertex = new Vertex<T>(value); this.vertices.push(_newVertex); this.adjoinList.set(_newVertex, []); } addEdge(valueOne: T, valueTwo: T): boolean { const _vertexOne = this.findVertex(valueOne); const _vertexTwo = this.findVertex(valueTwo); if (_vertexOne && _vertexTwo) { const _isAttachmentExist = this.adjoinList.get(_vertexOne)!.some((_adjacentVertex) => _adjacentVertex === _vertexTwo) || this.adjoinList.get(_vertexTwo)!.some((_adjacentVertex) => _adjacentVertex === _vertexOne); if (_isAttachmentExist) { console.warn('[addEdge] 指定的两个顶点已经存在连线关系,不需要重复指定'); return false; } else { this.adjoinList.get(_vertexOne)!.push(_vertexTwo); this.adjoinList.get(_vertexTwo)!.push(_vertexOne); return true; } } else { console.warn('[addEdge] 需要指定连线的顶点不存在于顶点列表中,指定连线失败'); return false; } } breadthFirstSearch(callbackFn?: (vertex: Vertex<T>) => void) { if (this.vertices.length === 0) { console.info('[breadthFirstSearch] 图结构中不包含任何顶点,无需遍历'); return; } const _verticesQueue = new SinglyQueue<Vertex<T>>(); _verticesQueue.enqueue(this.vertices[0]); const _visitedVertices: Set<Vertex<T>> = new Set(); _visitedVertices.add(this.vertices[0]); while (_verticesQueue.size > 0) { const _vertex = _verticesQueue.dequeue()!; callbackFn && callbackFn(_vertex); const _adjoinList = this.adjoinList.get(_vertex)!; if (!_adjoinList.length) continue; for (const _adjacentVertices of _adjoinList) { if (!_visitedVertices.has(_adjacentVertices)) { _visitedVertices.add(_adjacentVertices); _verticesQueue.enqueue(_adjacentVertices); } } } } depthFirstSearch(callbackFn: (vertex: Vertex<T>) => void) { if (this.vertices.length === 0) { console.info('[breadthFirstSearch] 图结构中不包含任何顶点,无需遍历'); return; } const _verticesStack = new Stack<Vertex<T>>(); _verticesStack.push(this.vertices[0]); const _visitedVertices = new Set<Vertex<T>>(); _visitedVertices.add(this.vertices[0]); while (_verticesStack.size > 0) { const _vertex = _verticesStack.pop()!; callbackFn && callbackFn(_vertex); const _adjoinList = this.adjoinList.get(_vertex)!; if (!_adjoinList.length) continue; const _adjoinListLength = _adjoinList.length; for (let _index = _adjoinListLength - 1; _index >= 0; _index--) { const _adjacentVertices = _adjoinList[_index]; if (!_visitedVertices.has(_adjacentVertices)) { _visitedVertices.add(_adjacentVertices); _verticesStack.push(_adjacentVertices); } } } } } export { Vertex, Graph, };