diff --git a/src/data-structures/graph/abstract-graph.ts b/src/data-structures/graph/abstract-graph.ts index 889c652..00f4586 100644 --- a/src/data-structures/graph/abstract-graph.ts +++ b/src/data-structures/graph/abstract-graph.ts @@ -156,10 +156,10 @@ export abstract class AbstractGraph< addVertex(keyOrVertex: VertexKey | VO, value?: V): boolean { if (keyOrVertex instanceof AbstractVertex) { - return this._addVertexOnly(keyOrVertex); + return this._addVertex(keyOrVertex); } else { const newVertex = this.createVertex(keyOrVertex, value); - return this._addVertexOnly(newVertex); + return this._addVertex(newVertex); } } @@ -242,14 +242,14 @@ export abstract class AbstractGraph< addEdge(srcOrEdge: VO | VertexKey | EO, dest?: VO | VertexKey, weight?: number, value?: E): boolean { if (srcOrEdge instanceof AbstractEdge) { - return this._addEdgeOnly(srcOrEdge); + return this._addEdge(srcOrEdge); } else { if (dest instanceof AbstractVertex || typeof dest === 'string' || typeof dest === 'number') { if (!(this.hasVertex(srcOrEdge) && this.hasVertex(dest))) return false; if (srcOrEdge instanceof AbstractVertex) srcOrEdge = srcOrEdge.key; if (dest instanceof AbstractVertex) dest = dest.key; const newEdge = this.createEdge(srcOrEdge, dest, weight, value); - return this._addEdgeOnly(newEdge); + return this._addEdge(newEdge); } else { throw new Error('dest must be a Vertex or vertex key while srcOrEdge is an Edge'); } @@ -1147,14 +1147,6 @@ export abstract class AbstractGraph< return this.tarjan(false, false, false, false).lowMap; } - /** - * The function `getCycles` returns a map of cycles found using the Tarjan algorithm. - * @returns The function `getCycles()` is returning a `Map`. - */ - getCycles(): Map { - return this.tarjan(false, false, false, true).cycles; - } - /** * The function "getCutVertexes" returns an array of cut vertexes using the Tarjan algorithm. * @returns an array of VO objects, specifically the cut vertexes. @@ -1180,6 +1172,55 @@ export abstract class AbstractGraph< return this.tarjan(false, true, false, false).bridges; } + /** + * O(V+E+C) + * O(V+C) + */ + getCycles(isInclude2Cycle: boolean = false): VertexKey[][] { + const cycles: VertexKey[][] = []; + const visited: Set = new Set(); + + const dfs = (vertex: VO, currentPath: VertexKey[], visited: Set) => { + if (visited.has(vertex)) { + if ((!isInclude2Cycle && currentPath.length > 2 || isInclude2Cycle && currentPath.length >= 2) && currentPath[0] === vertex.key) { + cycles.push([...currentPath]); + } + return; + } + + visited.add(vertex); + currentPath.push(vertex.key); + + for (const neighbor of this.getNeighbors(vertex)) { + neighbor && dfs(neighbor, currentPath, visited); + } + + visited.delete(vertex); + currentPath.pop(); + }; + + for (const vertex of this.vertexMap.values()) { + dfs(vertex, [], visited); + } + + // Use a set to eliminate duplicate cycles + const uniqueCycles = new Map(); + + for (const cycle of cycles) { + const sorted = [...cycle].sort().toString() + + if (uniqueCycles.has(sorted)) continue + else { + uniqueCycles.set(sorted, cycle) + } + } + + // Convert the unique cycles back to an array + return [...uniqueCycles].map(cycleString => + cycleString[1] + ); + } + /** * Time Complexity: O(n) * Space Complexity: O(n) @@ -1247,9 +1288,9 @@ export abstract class AbstractGraph< } } - protected abstract _addEdgeOnly(edge: EO): boolean; + protected abstract _addEdge(edge: EO): boolean; - protected _addVertexOnly(newVertex: VO): boolean { + protected _addVertex(newVertex: VO): boolean { if (this.hasVertex(newVertex)) { return false; // throw (new Error('Duplicated vertex key is not allowed')); diff --git a/src/data-structures/graph/directed-graph.ts b/src/data-structures/graph/directed-graph.ts index 39995ee..e863a3c 100644 --- a/src/data-structures/graph/directed-graph.ts +++ b/src/data-structures/graph/directed-graph.ts @@ -596,6 +596,7 @@ export class DirectedGraph< } } + /** * Time Complexity: O(1) * Space Complexity: O(1) @@ -605,13 +606,13 @@ export class DirectedGraph< * Time Complexity: O(1) * Space Complexity: O(1) * - * The function `_addEdgeOnly` adds an edge to a graph if the source and destination vertexMap exist. + * The function `_addEdge` adds an edge to a graph if the source and destination vertexMap exist. * @param {EO} edge - The parameter `edge` is of type `EO`, which represents an edge in a graph. It is the edge that * needs to be added to the graph. * @returns a boolean value. It returns true if the edge was successfully added to the graph, and false if either the * source or destination vertex does not exist in the graph. */ - protected _addEdgeOnly(edge: EO): boolean { + protected _addEdge(edge: EO): boolean { if (!(this.hasVertex(edge.src) && this.hasVertex(edge.dest))) { return false; } diff --git a/src/data-structures/graph/undirected-graph.ts b/src/data-structures/graph/undirected-graph.ts index 400e2d0..45241b9 100644 --- a/src/data-structures/graph/undirected-graph.ts +++ b/src/data-structures/graph/undirected-graph.ts @@ -381,7 +381,7 @@ export class UndirectedGraph< * @param {EO} edge - The parameter "edge" is of type EO, which represents an edge in a graph. * @returns a boolean value. */ - protected _addEdgeOnly(edge: EO): boolean { + protected _addEdge(edge: EO): boolean { for (const end of edge.vertexMap) { const endVertex = this._getVertex(end); if (endVertex === undefined) return false; diff --git a/src/data-structures/linked-list/doubly-linked-list.ts b/src/data-structures/linked-list/doubly-linked-list.ts index 62094a4..89273b4 100644 --- a/src/data-structures/linked-list/doubly-linked-list.ts +++ b/src/data-structures/linked-list/doubly-linked-list.ts @@ -70,6 +70,38 @@ export class DoublyLinkedList extends IterableElementBase { * Space Complexity: O(n) */ + /** + * Time Complexity: O(n), where n is the number of elements in the linked list. + * Space Complexity: O(1) + * + * The `get first` function returns the first node in a doubly linked list, or undefined if the list is empty. + * @returns The method `get first()` returns the first node of the doubly linked list, or `undefined` if the list is empty. + */ + get first(): E | undefined { + return this.head?.value; + } + + /** + * Time Complexity: O(1) + * Space Complexity: O(1) + */ + + /** + * Time Complexity: O(n), where n is the number of elements in the linked list. + * Space Complexity: O(1) + * + * The `get last` function returns the last node in a doubly linked list, or undefined if the list is empty. + * @returns The method `get last()` returns the last node of the doubly linked list, or `undefined` if the list is empty. + */ + get last(): E | undefined { + return this.tail?.value; + } + + /** + * Time Complexity: O(1) + * Space Complexity: O(1) + */ + /** * Time Complexity: O(n), where n is the size of the input array. * Space Complexity: O(n) @@ -141,7 +173,7 @@ export class DoublyLinkedList extends IterableElementBase { } /** - * Time Complexity: O(1) + * Time Complexity: O(n), where n is the number of elements in the linked list. * Space Complexity: O(1) */ @@ -168,7 +200,7 @@ export class DoublyLinkedList extends IterableElementBase { } /** - * Time Complexity: O(1) + * Time Complexity: O(n), where n is the number of elements in the linked list. * Space Complexity: O(1) */ @@ -399,11 +431,6 @@ export class DoublyLinkedList extends IterableElementBase { return false; } - /** - * Time Complexity: O(n), where n is the number of elements in the linked list. - * Space Complexity: O(1) - */ - /** * Time Complexity: O(n), where n is the number of elements in the linked list. * Space Complexity: O(1) @@ -434,11 +461,6 @@ export class DoublyLinkedList extends IterableElementBase { return true; } - /** - * Time Complexity: O(n), where n is the number of elements in the linked list. - * Space Complexity: O(1) - */ - /** * Time Complexity: O(n), where n is the number of elements in the linked list. * Space Complexity: O(1) @@ -475,6 +497,11 @@ export class DoublyLinkedList extends IterableElementBase { return false; } + /** + * Time Complexity: O(n), where n is the number of elements in the linked list. + * Space Complexity: O(1) + */ + /** * The function checks if a variable has a size greater than zero and returns a boolean value. * @returns A boolean value is being returned. @@ -483,6 +510,11 @@ export class DoublyLinkedList extends IterableElementBase { return this.size === 0; } + /** + * Time Complexity: O(n), where n is the number of elements in the linked list. + * Space Complexity: O(1) + */ + /** * The `clear` function resets the linked list by setting the head, tail, and size to undefined and 0 respectively. */ @@ -548,7 +580,7 @@ export class DoublyLinkedList extends IterableElementBase { /** * Time Complexity: O(n), where n is the number of elements in the linked list. - * Space Complexity: O(1) + * Space Complexity: O(n) */ /** @@ -575,7 +607,7 @@ export class DoublyLinkedList extends IterableElementBase { /** * Time Complexity: O(n), where n is the number of elements in the linked list. - * Space Complexity: O(1) + * Space Complexity: O(n) */ /** @@ -596,7 +628,7 @@ export class DoublyLinkedList extends IterableElementBase { } /** - * Time Complexity: O(n), where n is the number of elements in the linked list. + * Time Complexity: O(n) * Space Complexity: O(n) */ @@ -640,8 +672,8 @@ export class DoublyLinkedList extends IterableElementBase { } /** - * Time Complexity: O(n) - * Space Complexity: O(n) + * Time Complexity: O(1) + * Space Complexity: O(1) */ /** @@ -674,8 +706,8 @@ export class DoublyLinkedList extends IterableElementBase { } /** - * Time Complexity: O(n), where n is the number of elements in the linked list. - * Space Complexity: O(n) + * Time Complexity: O(1) + * Space Complexity: O(1) */ /** @@ -740,7 +772,7 @@ export class DoublyLinkedList extends IterableElementBase { } /** - * Time Complexity: O(1) + * Time Complexity: O(n), where n is the number of elements in the linked list. * Space Complexity: O(1) */ @@ -757,7 +789,7 @@ export class DoublyLinkedList extends IterableElementBase { } /** - * Time Complexity: O(1) + * Time Complexity: O(n), where n is the number of elements in the linked list. * Space Complexity: O(1) */ @@ -773,38 +805,6 @@ export class DoublyLinkedList extends IterableElementBase { this.unshift(value); } - /** - * Time Complexity: O(n), where n is the number of elements in the linked list. - * Space Complexity: O(1) - */ - - /** - * Time Complexity: O(n), where n is the number of elements in the linked list. - * Space Complexity: O(1) - * - * The `get first` function returns the first node in a doubly linked list, or undefined if the list is empty. - * @returns The method `get first()` returns the first node of the doubly linked list, or `undefined` if the list is empty. - */ - get first(): E | undefined { - return this.head?.value; - } - - /** - * Time Complexity: O(n), where n is the number of elements in the linked list. - * Space Complexity: O(1) - */ - - /** - * Time Complexity: O(n), where n is the number of elements in the linked list. - * Space Complexity: O(1) - * - * The `get last` function returns the last node in a doubly linked list, or undefined if the list is empty. - * @returns The method `get last()` returns the last node of the doubly linked list, or `undefined` if the list is empty. - */ - get last(): E | undefined { - return this.tail?.value; - } - /** * The function returns an iterator that iterates over the values of a linked list. */ diff --git a/src/data-structures/linked-list/singly-linked-list.ts b/src/data-structures/linked-list/singly-linked-list.ts index 041b407..b3d970d 100644 --- a/src/data-structures/linked-list/singly-linked-list.ts +++ b/src/data-structures/linked-list/singly-linked-list.ts @@ -348,7 +348,7 @@ export class SinglyLinkedList extends IterableElementBase { * @returns The `delete` method returns a boolean value. It returns `true` if the value or node is found and * successfully deleted from the linked list, and `false` if the value or node is not found in the linked list. */ - delete(valueOrNode: E | SinglyLinkedListNode | undefined ): boolean { + delete(valueOrNode: E | SinglyLinkedListNode | undefined): boolean { if (!valueOrNode) return false; let value: E; if (valueOrNode instanceof SinglyLinkedListNode) { diff --git a/src/data-structures/linked-list/skip-linked-list.ts b/src/data-structures/linked-list/skip-linked-list.ts index 360fcb9..8759a63 100644 --- a/src/data-structures/linked-list/skip-linked-list.ts +++ b/src/data-structures/linked-list/skip-linked-list.ts @@ -57,6 +57,45 @@ export class SkipList { return this._probability; } + /** + * Time Complexity: O(log n) - where n is the number of elements in the SkipList, as it traverses the levels of the SkipList. + * Space Complexity: O(1) - constant space, as it uses a fixed amount of space regardless of the size of the SkipList. + */ + + /** + * Time Complexity: O(1) - where n is the number of elements in the SkipList, as it traverses the levels of the SkipList. + * Space Complexity: O(1) - constant space, as it uses a fixed amount of space regardless of the size of the SkipList. + * + * Get the value of the first element (the smallest element) in the Skip List. + * @returns The value of the first element, or undefined if the Skip List is empty. + */ + get first(): V | undefined { + const firstNode = this.head.forward[0]; + return firstNode ? firstNode.value : undefined; + } + + /** + * Time Complexity: O(log n) - where n is the number of elements in the SkipList, as it traverses the levels of the SkipList. + * Space Complexity: O(1) - constant space, as it uses a fixed amount of space regardless of the size of the SkipList. + */ + + /** + * Time Complexity: O(log n) - where n is the number of elements in the SkipList, as it traverses the levels of the SkipList. + * Space Complexity: O(1) - constant space, as it uses a fixed amount of space regardless of the size of the SkipList. + * + * Get the value of the last element (the largest element) in the Skip List. + * @returns The value of the last element, or undefined if the Skip List is empty. + */ + get last(): V | undefined { + let current = this.head; + for (let i = this.level - 1; i >= 0; i--) { + while (current.forward[i]) { + current = current.forward[i]; + } + } + return current.value; + } + /** * Time Complexity: O(log n) - where n is the number of elements in the SkipList, as it traverses the levels of the SkipList. * Space Complexity: O(1) - constant space, as it uses a fixed amount of space regardless of the size of the SkipList. @@ -125,7 +164,7 @@ export class SkipList { } /** - * Time Complexity: O(log n) - where n is the number of elements in the SkipList, as it traverses the levels of the SkipList. + * Time Complexity: O(1) - where n is the number of elements in the SkipList, as it traverses the levels of the SkipList. * Space Complexity: O(1) - constant space, as it uses a fixed amount of space regardless of the size of the SkipList. */ @@ -181,45 +220,6 @@ export class SkipList { return false; } - /** - * Time Complexity: O(1) - where n is the number of elements in the SkipList, as it traverses the levels of the SkipList. - * Space Complexity: O(1) - constant space, as it uses a fixed amount of space regardless of the size of the SkipList. - */ - - /** - * Time Complexity: O(1) - where n is the number of elements in the SkipList, as it traverses the levels of the SkipList. - * Space Complexity: O(1) - constant space, as it uses a fixed amount of space regardless of the size of the SkipList. - * - * Get the value of the first element (the smallest element) in the Skip List. - * @returns The value of the first element, or undefined if the Skip List is empty. - */ - get first(): V | undefined { - const firstNode = this.head.forward[0]; - return firstNode ? firstNode.value : undefined; - } - - /** - * Time Complexity: O(log n) - where n is the number of elements in the SkipList, as it traverses the levels of the SkipList. - * Space Complexity: O(1) - constant space, as it uses a fixed amount of space regardless of the size of the SkipList. - */ - - /** - * Time Complexity: O(log n) - where n is the number of elements in the SkipList, as it traverses the levels of the SkipList. - * Space Complexity: O(1) - constant space, as it uses a fixed amount of space regardless of the size of the SkipList. - * - * Get the value of the last element (the largest element) in the Skip List. - * @returns The value of the last element, or undefined if the Skip List is empty. - */ - get last(): V | undefined { - let current = this.head; - for (let i = this.level - 1; i >= 0; i--) { - while (current.forward[i]) { - current = current.forward[i]; - } - } - return current.value; - } - /** * Time Complexity: O(log n) - where n is the number of elements in the SkipList, as it traverses the levels of the SkipList. * Space Complexity: O(1) - constant space, as it uses a fixed amount of space regardless of the size of the SkipList. diff --git a/src/data-structures/queue/queue.ts b/src/data-structures/queue/queue.ts index c0cb9d5..083ece2 100644 --- a/src/data-structures/queue/queue.ts +++ b/src/data-structures/queue/queue.ts @@ -49,6 +49,40 @@ export class Queue extends IterableElementBase { return this.nodes.length - this.offset; } + /** + * Time Complexity: O(1) - constant time as it retrieves the value at the current offset. + * Space Complexity: O(1) - no additional space is used. + * + * The `first` function returns the first element of the array `_nodes` if it exists, otherwise it returns `undefined`. + * @returns The `get first()` method returns the first element of the data structure, represented by the `_nodes` array at + * the `_offset` index. If the data structure is empty (size is 0), it returns `undefined`. + */ + get first(): E | undefined { + return this.size > 0 ? this.nodes[this.offset] : undefined; + } + + /** + * Time Complexity: O(1) - constant time as it adds an element to the end of the array. + * Space Complexity: O(1) - no additional space is used. + */ + + /** + * Time Complexity: O(1) - constant time as it retrieves the value at the current offset. + * Space Complexity: O(1) - no additional space is used. + * + * The `last` function returns the last element in an array-like data structure, or undefined if the structure is empty. + * @returns The method `get last()` returns the last element of the `_nodes` array if the array is not empty. If the + * array is empty, it returns `undefined`. + */ + get last(): E | undefined { + return this.size > 0 ? this.nodes[this.nodes.length - 1] : undefined; + } + + /** + * Time Complexity: O(n) - where n is the number of elements in the queue. In the worst case, it may need to shift all elements to update the offset. + * Space Complexity: O(1) - no additional space is used. + */ + /** * The function "fromArray" creates a new Queue object from an array of elements.Creates a queue from an existing array. * @public @@ -62,7 +96,7 @@ export class Queue extends IterableElementBase { } /** - * Time Complexity: O(1) - constant time as it adds an element to the end of the array. + * Time Complexity: O(1) - constant time as it retrieves the value at the current offset. * Space Complexity: O(1) - no additional space is used. */ @@ -80,7 +114,7 @@ export class Queue extends IterableElementBase { } /** - * Time Complexity: O(n) - where n is the number of elements in the queue. In the worst case, it may need to shift all elements to update the offset. + * Time Complexity: O(1) - constant time as it retrieves the value at the current offset. * Space Complexity: O(1) - no additional space is used. */ @@ -107,23 +141,6 @@ export class Queue extends IterableElementBase { return first; } - /** - * Time Complexity: O(1) - constant time as it retrieves the value at the current offset. - * Space Complexity: O(1) - no additional space is used. - */ - - /** - * Time Complexity: O(1) - constant time as it retrieves the value at the current offset. - * Space Complexity: O(1) - no additional space is used. - * - * The `first` function returns the first element of the array `_nodes` if it exists, otherwise it returns `undefined`. - * @returns The `get first()` method returns the first element of the data structure, represented by the `_nodes` array at - * the `_offset` index. If the data structure is empty (size is 0), it returns `undefined`. - */ - get first(): E | undefined { - return this.size > 0 ? this.nodes[this.offset] : undefined; - } - /** * Time Complexity: O(1) - constant time as it retrieves the value at the current offset. * Space Complexity: O(1) - no additional space is used. @@ -141,23 +158,6 @@ export class Queue extends IterableElementBase { return this.first; } - /** - * Time Complexity: O(1) - constant time as it retrieves the value at the current offset. - * Space Complexity: O(1) - no additional space is used. - */ - - /** - * Time Complexity: O(1) - constant time as it retrieves the value at the current offset. - * Space Complexity: O(1) - no additional space is used. - * - * The `last` function returns the last element in an array-like data structure, or undefined if the structure is empty. - * @returns The method `get last()` returns the last element of the `_nodes` array if the array is not empty. If the - * array is empty, it returns `undefined`. - */ - get last(): E | undefined { - return this.size > 0 ? this.nodes[this.nodes.length - 1] : undefined; - } - /** * Time Complexity: O(1) - constant time as it retrieves the value at the current offset. * Space Complexity: O(1) - no additional space is used. @@ -358,12 +358,20 @@ export class Queue extends IterableElementBase { * 4. Frequent Enqueuing and Dequeuing Operations: If your application involves frequent enqueuing and dequeuing operations and is less concerned with random access, then LinkedListQueue is a good choice. */ export class LinkedListQueue extends SinglyLinkedList { + /** + * The `get first` function returns the value of the head node in a linked list, or `undefined` if the list is empty. + * @returns The `get first()` method is returning the value of the `head` node if it exists, otherwise it returns `undefined`. + */ + get first(): E | undefined { + return this.head?.value; + } + /** * The enqueue function adds a value to the end of an array. * @param {E} value - The value parameter represents the value that you want to add to the queue. */ enqueue(value: E): boolean { - return this.push(value); + return this.push(value); } /** @@ -374,14 +382,6 @@ export class LinkedListQueue extends SinglyLinkedList { return this.shift(); } - /** - * The `get first` function returns the value of the head node in a linked list, or `undefined` if the list is empty. - * @returns The `get first()` method is returning the value of the `head` node if it exists, otherwise it returns `undefined`. - */ - get first(): E | undefined { - return this.head?.value; - } - /** * The `peek` function returns the value of the head node in a linked list, or `undefined` if the list is empty. * @returns The `peek()` method is returning the value of the `head` node if it exists, otherwise it returns `undefined`. diff --git a/test/unit/data-structures/graph/abstract-graph.test.ts b/test/unit/data-structures/graph/abstract-graph.test.ts index dd2387b..502b2b6 100644 --- a/test/unit/data-structures/graph/abstract-graph.test.ts +++ b/test/unit/data-structures/graph/abstract-graph.test.ts @@ -66,7 +66,7 @@ class MyGraph< return edge ? undefined : undefined; } - protected _addEdgeOnly(edge: EO): boolean { + protected _addEdge(edge: EO): boolean { return edge ? true : true; } } diff --git a/test/unit/data-structures/graph/directed-graph.test.ts b/test/unit/data-structures/graph/directed-graph.test.ts index 54a07f5..f0d5b1d 100644 --- a/test/unit/data-structures/graph/directed-graph.test.ts +++ b/test/unit/data-structures/graph/directed-graph.test.ts @@ -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(2); + expect(cycles.length).toBe(2); expect(scCs.size).toBe(5); expect(bridges.length).toBe(4); expect(cutVertexes.length).toBe(4); @@ -688,8 +688,53 @@ describe('DirectedGraph getCycles', () => { graph.addEdge('D', 'E'); graph.addEdge('E', 'B'); const cycles = graph.getCycles(); - expect(cycles.size).toBe(1); - expect(cycles.get(2)).toEqual( [{ "key": "B", "value": undefined }, { "key": "D", "value": undefined }, { "key": "E", "value": undefined }]); + expect(cycles.length).toBe(1); + expect(cycles[0]).toEqual(["B", "D", "E"]); }) + + test('should simple cycles graph getCycles return correct result', () => { + const graph = new DirectedGraph(); + + graph.addVertex('A'); + graph.addVertex('B'); + graph.addVertex('C'); + graph.addVertex('D'); + + graph.addEdge('A', 'B'); + graph.addEdge('B', 'C'); + graph.addEdge('C', 'A'); + graph.addEdge('A', 'D'); + graph.addEdge('D', 'C'); + const cycles = graph.getCycles(); + expect(cycles.length).toBe(2) + expect(cycles).toEqual([["A", "B", "C"], ["A", "D", "C"]]) + }); + + test('should 3 cycles graph getCycles return correct result', () => { + const graph = new DirectedGraph(); + + graph.addVertex('A'); + graph.addVertex('B'); + graph.addVertex('C'); + graph.addVertex('D'); + graph.addVertex('E'); + graph.addVertex('F'); + graph.addVertex('G'); + + graph.addEdge('A', 'B'); + graph.addEdge('A', 'C'); + graph.addEdge('B', 'D'); + graph.addEdge('C', 'D'); + graph.addEdge('D', 'E'); + graph.addEdge('E', 'B'); + graph.addEdge('B', 'F'); + graph.addEdge('F', 'E'); + graph.addEdge('C', 'G'); + graph.addEdge('G', 'A'); + + const cycles = graph.getCycles(); + expect(cycles.length).toBe(3) + expect(cycles).toEqual([["A", "C", "G"], ["B", "D", "E"], ["B", "F", "E"]]); + }); }) diff --git a/test/unit/data-structures/graph/undirected-graph.test.ts b/test/unit/data-structures/graph/undirected-graph.test.ts index 8c887bc..1f93d18 100644 --- a/test/unit/data-structures/graph/undirected-graph.test.ts +++ b/test/unit/data-structures/graph/undirected-graph.test.ts @@ -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(2); + expect(cycles.length).toBe(3); expect(scCs.size).toBe(5); expect(bridges.length).toBe(4); expect(cutVertexes.length).toBe(4); @@ -277,8 +277,52 @@ describe('UndirectedGraph getCycles', () => { graph.addEdge('D', 'E'); graph.addEdge('E', 'B'); const cycles = graph.getCycles(); - expect(cycles.size).toBe(2); - expect(cycles.get(1)).toEqual([{ "key": "A", "value": "A" }, { "key": "B", "value": "B" }, { "key": "D", "value": "D" }, { "key": "C", "value": "C" }]); - expect(cycles.get(2)).toEqual([{ "key": "B", "value": "B" }, { "key": "D", "value": "D" }, { "key": "E", "value": "E" }]); + expect(cycles.length).toBe(3); + expect(cycles).toEqual([["A", "B", "D", "C"], ["A", "B", "E", "D", "C"], ["B", "D", "E"]]); }) + + test('should simple cycles graph getCycles return correct result', () => { + const graph = new UndirectedGraph(); + + graph.addVertex('A'); + graph.addVertex('B'); + graph.addVertex('C'); + graph.addVertex('D'); + + graph.addEdge('A', 'B'); + graph.addEdge('B', 'C'); + graph.addEdge('C', 'A'); + graph.addEdge('A', 'D'); + graph.addEdge('D', 'C'); + const cycles = graph.getCycles(); + expect(cycles.length).toBe(3) + expect(cycles).toEqual([["A", "B", "C"], ["A", "B", "C", "D"], ["A", "C", "D"]]) + }); + + test('should 3 cycles graph getCycles return correct result', () => { + const graph = new UndirectedGraph(); + + graph.addVertex('A'); + graph.addVertex('B'); + graph.addVertex('C'); + graph.addVertex('D'); + graph.addVertex('E'); + graph.addVertex('F'); + graph.addVertex('G'); + + graph.addEdge('A', 'B'); + graph.addEdge('A', 'C'); + graph.addEdge('B', 'D'); + graph.addEdge('C', 'D'); + graph.addEdge('D', 'E'); + graph.addEdge('E', 'B'); + graph.addEdge('B', 'F'); + graph.addEdge('F', 'E'); + graph.addEdge('C', 'G'); + graph.addEdge('G', 'A'); + + const cycles = graph.getCycles(); + expect(cycles.length).toBe(10) + expect(cycles).toEqual([["A", "B", "D", "C"], ["A", "B", "D", "C", "G"], ["A", "B", "E", "D", "C"], ["A", "B", "E", "D", "C", "G"], ["A", "B", "F", "E", "D", "C"], ["A", "B", "F", "E", "D", "C", "G"], ["A", "C", "G"], ["B", "D", "E"], ["B", "D", "E", "F"], ["B", "E", "F"]]); + }); }) \ No newline at end of file diff --git a/test/unit/data-structures/heap/heap.test.ts b/test/unit/data-structures/heap/heap.test.ts index 275bee3..a754a7b 100644 --- a/test/unit/data-structures/heap/heap.test.ts +++ b/test/unit/data-structures/heap/heap.test.ts @@ -5,7 +5,12 @@ import { logBigOMetricsWrap } from '../../../utils'; describe('Heap Operation Test', () => { it('should numeric heap work well', function () { const minNumHeap = new MinHeap(); - minNumHeap.add(1);minNumHeap.add(6);minNumHeap.add(2);minNumHeap.add(0);minNumHeap.add(5);minNumHeap.add(9); + minNumHeap.add(1); + minNumHeap.add(6); + minNumHeap.add(2); + minNumHeap.add(0); + minNumHeap.add(5); + minNumHeap.add(9); expect(minNumHeap.has(1)).toBe(true); expect(minNumHeap.has(2)).toBe(true); expect(minNumHeap.poll()).toBe(0);