mirror of
https://github.com/zrwusa/data-structure-typed.git
synced 2024-11-23 12:54:04 +00:00
fix: bug fixed #58, DirectedGraph.getCycles returns an inexisting cycle. feat: hasValue method for HashMap.
This commit is contained in:
parent
f0927e8b0a
commit
e113a99b26
|
@ -1086,15 +1086,33 @@ export abstract class AbstractGraph<
|
|||
}
|
||||
|
||||
const cycles: Map<number, VO[]> = new Map();
|
||||
if (needCycles) {
|
||||
let SCCs: Map<number, VO[]> = new Map();
|
||||
if (SCCs.size < 1) {
|
||||
SCCs = getSCCs();
|
||||
}
|
||||
|
||||
SCCs.forEach((SCC, low) => {
|
||||
if (SCC.length > 1) {
|
||||
cycles.set(low, SCC);
|
||||
if (needCycles) {
|
||||
const visitedMap: Map<VO, boolean> = new Map();
|
||||
const stack: VO[] = [];
|
||||
const findCyclesDFS = (cur: VO, parent: VO | undefined) => {
|
||||
visitedMap.set(cur, true);
|
||||
stack.push(cur);
|
||||
|
||||
const neighbors = this.getNeighbors(cur);
|
||||
|
||||
for (const neighbor of neighbors) {
|
||||
if (!visitedMap.get(neighbor)) {
|
||||
findCyclesDFS(neighbor, cur);
|
||||
} else if (stack.includes(neighbor) && neighbor !== parent) {
|
||||
const cycleStartIndex = stack.indexOf(neighbor);
|
||||
const cycle = stack.slice(cycleStartIndex);
|
||||
const cycleLow = Math.min(...cycle.map(v => dfnMap.get(v) || Infinity));
|
||||
cycles.set(cycleLow, cycle);
|
||||
}
|
||||
}
|
||||
|
||||
stack.pop();
|
||||
};
|
||||
|
||||
vertexMap.forEach(v => {
|
||||
if (!visitedMap.get(v)) {
|
||||
findCyclesDFS(v, undefined);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -411,6 +411,13 @@ export class LinkedHashMap<K = any, V = any> extends IterableEntryBase<K, V> {
|
|||
}
|
||||
}
|
||||
|
||||
hasValue(value: V): boolean {
|
||||
for (const [, elementValue] of this) {
|
||||
if (elementValue === value) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
setMany(entries: Iterable<[K, V]>): void {
|
||||
for (const entry of entries) {
|
||||
const [key, value] = entry;
|
||||
|
|
|
@ -188,7 +188,7 @@ export class Queue<E = any> extends IterableElementBase<E> {
|
|||
* @param {E} value - The value parameter represents the value that you want to add to the queue.
|
||||
*/
|
||||
enqueue(value: E) {
|
||||
this.push(value);
|
||||
return this.push(value);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -588,7 +588,7 @@ describe('cycles, strongly connected components, bridges, articular points in Di
|
|||
const cutVertexes = graph.getCutVertexes();
|
||||
const dfnMap = graph.getDFNMap();
|
||||
const lowMap = graph.getLowMap();
|
||||
expect(cycles.size).toBe(1);
|
||||
expect(cycles.size).toBe(2);
|
||||
expect(scCs.size).toBe(5);
|
||||
expect(bridges.length).toBe(4);
|
||||
expect(cutVertexes.length).toBe(4);
|
||||
|
@ -673,3 +673,24 @@ describe('DirectedGraph iterative Methods', () => {
|
|||
})
|
||||
});
|
||||
|
||||
describe('DirectedGraph getCycles', () => {
|
||||
test('should getCycles return correct result', () => {
|
||||
const graph = new DirectedGraph();
|
||||
graph.addVertex('A');
|
||||
graph.addVertex('B');
|
||||
graph.addVertex('C');
|
||||
graph.addVertex('D');
|
||||
graph.addVertex('E');
|
||||
graph.addEdge('A', 'B');
|
||||
graph.addEdge('A', 'C');
|
||||
graph.addEdge('B', 'D');
|
||||
graph.addEdge('C', 'D');
|
||||
graph.addEdge('D', 'E');
|
||||
graph.addEdge('E', 'B');
|
||||
const cycles = graph.getCycles();
|
||||
expect(cycles.size).toBe(1);
|
||||
|
||||
console.log(Array.from(cycles.values()));
|
||||
})
|
||||
})
|
||||
|
||||
|
|
|
@ -237,7 +237,7 @@ describe('cycles, strongly connected components, bridges, articular points in Un
|
|||
const cutVertexes = graph.getCutVertexes();
|
||||
const dfnMap = graph.getDFNMap();
|
||||
const lowMap = graph.getLowMap();
|
||||
expect(cycles.size).toBe(1);
|
||||
expect(cycles.size).toBe(2);
|
||||
expect(scCs.size).toBe(5);
|
||||
expect(bridges.length).toBe(4);
|
||||
expect(cutVertexes.length).toBe(4);
|
||||
|
@ -260,4 +260,24 @@ it("Should return Infinity if dest is not found", () => {
|
|||
|
||||
const minCost01 = graph.getMinCostBetween(0, 1, true);
|
||||
expect(minCost01).toBe(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('UndirectedGraph getCycles', () => {
|
||||
test('should getCycles return correct result', () => {
|
||||
const graph = new UndirectedGraph();
|
||||
graph.addVertex('A');
|
||||
graph.addVertex('B');
|
||||
graph.addVertex('C');
|
||||
graph.addVertex('D');
|
||||
graph.addVertex('E');
|
||||
graph.addEdge('A', 'B');
|
||||
graph.addEdge('A', 'C');
|
||||
graph.addEdge('B', 'D');
|
||||
graph.addEdge('C', 'D');
|
||||
graph.addEdge('D', 'E');
|
||||
graph.addEdge('E', 'B');
|
||||
const cycles = graph.getCycles();
|
||||
expect(cycles.size).toBe(2);
|
||||
console.log(Array.from(cycles.values()));
|
||||
})
|
||||
})
|
Loading…
Reference in a new issue