mirror of
https://github.com/zrwusa/data-structure-typed.git
synced 2024-11-23 12:54:04 +00:00
Enable adding nodes using both Vertex instances and the vertex parameter in the Graph. For adding edges, support both Edge instances and the src, dest parameter approach simultaneously.
This commit is contained in:
parent
8ac4e0e7c4
commit
0b330aeadd
70
README.md
70
README.md
|
@ -351,8 +351,8 @@ let graph: DirectedGraph<DirectedVertex, DirectedEdge>;
|
|||
const vertex1 = new DirectedVertex('A');
|
||||
const vertex2 = new DirectedVertex('B');
|
||||
|
||||
graph.addVertex(vertex1);
|
||||
graph.addVertex(vertex2);
|
||||
graph._addVertexOnly(vertex1);
|
||||
graph._addVertexOnly(vertex2);
|
||||
|
||||
expect(graph.hasVertex(vertex1)).toBe(true);
|
||||
expect(graph.hasVertex(vertex2)).toBe(true);
|
||||
|
@ -363,9 +363,9 @@ let graph: DirectedGraph<DirectedVertex, DirectedEdge>;
|
|||
const vertex2 = new DirectedVertex('B');
|
||||
const edge = new DirectedEdge('A', 'B');
|
||||
|
||||
graph.addVertex(vertex1);
|
||||
graph.addVertex(vertex2);
|
||||
graph.addEdge(edge);
|
||||
graph._addVertexOnly(vertex1);
|
||||
graph._addVertexOnly(vertex2);
|
||||
graph._addEdgeOnly(edge);
|
||||
|
||||
expect(graph.hasEdge('A', 'B')).toBe(true);
|
||||
expect(graph.hasEdge('B', 'A')).toBe(false);
|
||||
|
@ -376,9 +376,9 @@ let graph: DirectedGraph<DirectedVertex, DirectedEdge>;
|
|||
const vertex2 = new DirectedVertex('B');
|
||||
const edge = new DirectedEdge('A', 'B');
|
||||
|
||||
graph.addVertex(vertex1);
|
||||
graph.addVertex(vertex2);
|
||||
graph.addEdge(edge);
|
||||
graph._addVertexOnly(vertex1);
|
||||
graph._addVertexOnly(vertex2);
|
||||
graph._addEdgeOnly(edge);
|
||||
|
||||
expect(graph.removeEdge(edge)).toBe(edge);
|
||||
expect(graph.hasEdge('A', 'B')).toBe(false);
|
||||
|
@ -391,11 +391,11 @@ let graph: DirectedGraph<DirectedVertex, DirectedEdge>;
|
|||
const edgeAB = new DirectedEdge('A', 'B');
|
||||
const edgeBC = new DirectedEdge('B', 'C');
|
||||
|
||||
graph.addVertex(vertexA);
|
||||
graph.addVertex(vertexB);
|
||||
graph.addVertex(vertexC);
|
||||
graph.addEdge(edgeAB);
|
||||
graph.addEdge(edgeBC);
|
||||
graph._addVertexOnly(vertexA);
|
||||
graph._addVertexOnly(vertexB);
|
||||
graph._addVertexOnly(vertexC);
|
||||
graph._addEdgeOnly(edgeAB);
|
||||
graph._addEdgeOnly(edgeBC);
|
||||
|
||||
const topologicalOrder = graph.topologicalSort();
|
||||
if (topologicalOrder) expect(topologicalOrder.map(v => v.id)).toEqual(['A', 'B', 'C']);
|
||||
|
@ -450,18 +450,18 @@ describe('DirectedGraph Test3', () => {
|
|||
const vertex7 = new MyVertex(7, 'data7');
|
||||
const vertex8 = new MyVertex(8, 'data8');
|
||||
const vertex9 = new MyVertex(9, 'data9');
|
||||
myGraph.addVertex(vertex1);
|
||||
myGraph.addVertex(vertex2);
|
||||
myGraph.addVertex(vertex3);
|
||||
myGraph.addVertex(vertex4);
|
||||
myGraph.addVertex(vertex5);
|
||||
myGraph.addVertex(vertex6);
|
||||
myGraph.addVertex(vertex7);
|
||||
myGraph.addVertex(vertex8);
|
||||
myGraph.addVertex(vertex9);
|
||||
myGraph._addVertexOnly(vertex1);
|
||||
myGraph._addVertexOnly(vertex2);
|
||||
myGraph._addVertexOnly(vertex3);
|
||||
myGraph._addVertexOnly(vertex4);
|
||||
myGraph._addVertexOnly(vertex5);
|
||||
myGraph._addVertexOnly(vertex6);
|
||||
myGraph._addVertexOnly(vertex7);
|
||||
myGraph._addVertexOnly(vertex8);
|
||||
myGraph._addVertexOnly(vertex9);
|
||||
|
||||
myGraph.addEdge(new MyEdge(1, 2, 10, 'edge-data1-2'));
|
||||
myGraph.addEdge(new MyEdge(2, 1, 20, 'edge-data2-1'));
|
||||
myGraph._addEdgeOnly(new MyEdge(1, 2, 10, 'edge-data1-2'));
|
||||
myGraph._addEdgeOnly(new MyEdge(2, 1, 20, 'edge-data2-1'));
|
||||
|
||||
expect(myGraph.getEdge(1, 2)).toBeTruthy();
|
||||
expect(myGraph.getEdge(2, 1)).toBeTruthy();
|
||||
|
@ -470,17 +470,17 @@ describe('DirectedGraph Test3', () => {
|
|||
myGraph.removeEdgeBetween(1, 2);
|
||||
expect(myGraph.getEdge(1, 2)).toBeFalsy();
|
||||
|
||||
myGraph.addEdge(new MyEdge(3, 1, 3, 'edge-data-3-1'));
|
||||
myGraph.addEdge(new MyEdge(1, 9, 19, 'edge-data1-9'));
|
||||
myGraph.addEdge(new MyEdge(9, 7, 97, 'edge-data9-7'));
|
||||
myGraph.addEdge(new MyEdge(7, 9, 79, 'edge-data7-9'));
|
||||
myGraph.addEdge(new MyEdge(1, 4, 14, 'edge-data1-4'));
|
||||
myGraph.addEdge(new MyEdge(4, 7, 47, 'edge-data4-7'));
|
||||
myGraph.addEdge(new MyEdge(1, 2, 12, 'edge-data1-2'));
|
||||
myGraph.addEdge(new MyEdge(2, 3, 23, 'edge-data2-3'));
|
||||
myGraph.addEdge(new MyEdge(3, 5, 35, 'edge-data3-5'));
|
||||
myGraph.addEdge(new MyEdge(5, 7, 57, 'edge-data5-7'));
|
||||
myGraph.addEdge(new MyEdge(7, 3, 73, 'edge-data7-3'));
|
||||
myGraph._addEdgeOnly(new MyEdge(3, 1, 3, 'edge-data-3-1'));
|
||||
myGraph._addEdgeOnly(new MyEdge(1, 9, 19, 'edge-data1-9'));
|
||||
myGraph._addEdgeOnly(new MyEdge(9, 7, 97, 'edge-data9-7'));
|
||||
myGraph._addEdgeOnly(new MyEdge(7, 9, 79, 'edge-data7-9'));
|
||||
myGraph._addEdgeOnly(new MyEdge(1, 4, 14, 'edge-data1-4'));
|
||||
myGraph._addEdgeOnly(new MyEdge(4, 7, 47, 'edge-data4-7'));
|
||||
myGraph._addEdgeOnly(new MyEdge(1, 2, 12, 'edge-data1-2'));
|
||||
myGraph._addEdgeOnly(new MyEdge(2, 3, 23, 'edge-data2-3'));
|
||||
myGraph._addEdgeOnly(new MyEdge(3, 5, 35, 'edge-data3-5'));
|
||||
myGraph._addEdgeOnly(new MyEdge(5, 7, 57, 'edge-data5-7'));
|
||||
myGraph._addEdgeOnly(new MyEdge(7, 3, 73, 'edge-data7-3'));
|
||||
|
||||
const topologicalSorted = myGraph.topologicalSort();
|
||||
expect(topologicalSorted).toBeNull();
|
||||
|
|
|
@ -139,12 +139,19 @@ export abstract class AbstractGraph<V extends AbstractVertex<any>, E extends Abs
|
|||
|
||||
abstract getEdge(srcOrId: V | VertexId, destOrId: V | VertexId): E | null;
|
||||
|
||||
createAddVertex(id: VertexId, val?: V['val']): boolean {
|
||||
const newVertex = this.createVertex(id, val);
|
||||
return this.addVertex(newVertex);
|
||||
addVertex(vertex: V): boolean
|
||||
addVertex(id: VertexId , val?: V['val']): boolean
|
||||
addVertex(idOrVertex: VertexId | V, val?: V['val']): boolean {
|
||||
if (idOrVertex instanceof AbstractVertex) {
|
||||
return this._addVertexOnly(idOrVertex);
|
||||
|
||||
} else {
|
||||
const newVertex = this.createVertex(idOrVertex, val);
|
||||
return this._addVertexOnly(newVertex);
|
||||
}
|
||||
}
|
||||
|
||||
addVertex(newVertex: V): boolean {
|
||||
protected _addVertexOnly(newVertex: V): boolean {
|
||||
if (this.hasVertex(newVertex)) {
|
||||
return false;
|
||||
// throw (new Error('Duplicated vertex id is not allowed'));
|
||||
|
@ -199,14 +206,25 @@ export abstract class AbstractGraph<V extends AbstractVertex<any>, E extends Abs
|
|||
return !!edge;
|
||||
}
|
||||
|
||||
createAddEdge(src: V | VertexId, dest: V | VertexId, weight: number, val: E['val']): boolean {
|
||||
if (src instanceof AbstractVertex) src = src.id;
|
||||
if (dest instanceof AbstractVertex) dest = dest.id;
|
||||
const newEdge = this.createEdge(src, dest, weight, val);
|
||||
return this.addEdge(newEdge);
|
||||
addEdge(edge: E): boolean
|
||||
addEdge(src: V | VertexId, dest: V | VertexId, weight: number, val?: E['val']): boolean
|
||||
addEdge(srcOrEdge: V | VertexId | E, dest?: V | VertexId, weight?: number, val?: E['val']): boolean {
|
||||
if (srcOrEdge instanceof AbstractEdge) {
|
||||
return this._addEdgeOnly(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.id;
|
||||
if (dest instanceof AbstractVertex) dest = dest.id;
|
||||
const newEdge = this.createEdge(srcOrEdge, dest, weight, val);
|
||||
return this._addEdgeOnly(newEdge);
|
||||
} else {
|
||||
throw new Error('dest must be a Vertex or vertex id while srcOrEdge is an Edge')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
abstract addEdge(edge: E): boolean;
|
||||
protected abstract _addEdgeOnly(edge: E): boolean;
|
||||
|
||||
/**
|
||||
* The function sets the weight of an edge between two vertices in a graph.
|
||||
|
|
|
@ -141,13 +141,13 @@ export class DirectedGraph<V extends DirectedVertex<any> = DirectedVertex, E ext
|
|||
}
|
||||
|
||||
/**
|
||||
* The `addEdge` function adds a directed edge to a graph if the source and destination vertices exist.
|
||||
* The `_addEdgeOnly` function adds a directed edge to a graph if the source and destination vertices exist.
|
||||
* @param edge - The parameter `edge` is of type `E`, which represents a directed edge in a graph. It
|
||||
* contains two properties:
|
||||
* @returns The method `addEdge` returns a boolean value. It returns `true` if the edge was successfully added to the
|
||||
* @returns The method `_addEdgeOnly` 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 of the edge is not present in the graph.
|
||||
*/
|
||||
addEdge(edge: E): boolean {
|
||||
protected _addEdgeOnly(edge: E): boolean {
|
||||
if (!(this.hasVertex(edge.src) && this.hasVertex(edge.dest))) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -120,7 +120,7 @@ export class UndirectedGraph<V extends UndirectedVertex<any> = UndirectedVertex,
|
|||
* array of two vertices connected by the edge.
|
||||
* @returns a boolean value.
|
||||
*/
|
||||
addEdge(edge: E): boolean {
|
||||
protected _addEdgeOnly(edge: E): boolean {
|
||||
for (const end of edge.vertices) {
|
||||
const endVertex = this._getVertex(end);
|
||||
if (endVertex === null) return false;
|
||||
|
|
|
@ -8,9 +8,9 @@ export interface IAbstractGraph<V, E> {
|
|||
|
||||
// _getVertexId(vertexOrId: V | VertexId): VertexId;
|
||||
|
||||
createAddVertex(id: VertexId, val?: V): boolean;
|
||||
addVertex(id: VertexId, val?: V): boolean;
|
||||
|
||||
addVertex(newVertex: V): boolean;
|
||||
// _addVertexOnly(newVertex: V): boolean;
|
||||
|
||||
removeVertex(vertexOrId: V | VertexId): boolean;
|
||||
|
||||
|
@ -26,9 +26,9 @@ export interface IAbstractGraph<V, E> {
|
|||
|
||||
edgeSet(): E[];
|
||||
|
||||
createAddEdge(src: V | VertexId, dest: V | VertexId, weight: number, val: E): boolean;
|
||||
addEdge(src: V | VertexId, dest: V | VertexId, weight: number, val: E): boolean;
|
||||
|
||||
addEdge(edge: E): boolean;
|
||||
// _addEdgeOnly(edge: E): boolean;
|
||||
|
||||
removeEdge(edge: E): E | null;
|
||||
|
||||
|
|
|
@ -116,11 +116,11 @@ describe('Inherit from DirectedGraph and perform operations', () => {
|
|||
});
|
||||
|
||||
it('Add vertices', () => {
|
||||
myGraph.addVertex(new MyVertex(1, 'data1'));
|
||||
myGraph.addVertex(new MyVertex(2, 'data2'));
|
||||
myGraph.addVertex(new MyVertex(3, 'data3'));
|
||||
myGraph.addVertex(new MyVertex(4, 'data4'));
|
||||
myGraph.addVertex(new MyVertex(5, 'data5'));
|
||||
myGraph.addVertex(1, 'data1');
|
||||
myGraph.addVertex(2, 'data2');
|
||||
myGraph.addVertex(3, 'data3');
|
||||
myGraph.addVertex(4, 'data4');
|
||||
myGraph.addVertex(5, 'data5');
|
||||
myGraph.addVertex(new MyVertex(6, 'data6'));
|
||||
myGraph.addVertex(new MyVertex(7, 'data7'));
|
||||
myGraph.addVertex(new MyVertex(8, 'data8'));
|
||||
|
@ -129,9 +129,9 @@ describe('Inherit from DirectedGraph and perform operations', () => {
|
|||
});
|
||||
|
||||
it('Add edges', () => {
|
||||
myGraph.addVertex(new MyVertex(1, 'data1'));
|
||||
myGraph.addVertex(new MyVertex(2, 'data2'));
|
||||
myGraph.addEdge(new MyEdge(1, 2, 10, 'edge-data1-2'));
|
||||
myGraph.addVertex(1, 'data1');
|
||||
myGraph.addVertex(2, 'data2');
|
||||
myGraph.addEdge(1, 2, 10, 'edge-data1-2');
|
||||
myGraph.addEdge(new MyEdge(2, 1, 20, 'edge-data2-1'));
|
||||
|
||||
expect(myGraph.edgeSet().length).toBe(2);
|
||||
|
@ -141,9 +141,9 @@ describe('Inherit from DirectedGraph and perform operations', () => {
|
|||
});
|
||||
|
||||
it('Get edge', () => {
|
||||
myGraph.createAddVertex(1, 'val1');
|
||||
myGraph.createAddVertex(2, 'val1');
|
||||
myGraph.createAddEdge(1, 2, 1, 'val1');
|
||||
myGraph.addVertex(1, 'val1');
|
||||
myGraph.addVertex(2, 'val1');
|
||||
myGraph.addEdge(1, 2, 1, 'val1');
|
||||
const edge1 = myGraph.getEdge(1, 2);
|
||||
const edge2 = myGraph.getEdge(myGraph.getVertex(1), myGraph.getVertex(2));
|
||||
const edge3 = myGraph.getEdge(1, '100');
|
||||
|
@ -167,9 +167,9 @@ describe('Inherit from DirectedGraph and perform operations', () => {
|
|||
});
|
||||
|
||||
it('Remove edge between vertices', () => {
|
||||
myGraph.addVertex(new MyVertex(1, 'data1'));
|
||||
myGraph.addVertex(new MyVertex(2, 'data2'));
|
||||
myGraph.addEdge(new MyEdge(1, 2, 10, 'edge-data1-2'));
|
||||
myGraph.addVertex(1, 'data1');
|
||||
myGraph.addVertex(2, 'data2');
|
||||
myGraph.addEdge(1, 2, 10, 'edge-data1-2');
|
||||
|
||||
const removedEdge = myGraph.removeEdgeSrcToDest(1, 2);
|
||||
const edgeAfterRemoval = myGraph.getEdge(1, 2);
|
||||
|
@ -249,24 +249,25 @@ describe('Inherit from DirectedGraph and perform operations test2.', () => {
|
|||
myGraph.removeEdgeSrcToDest(1, 2);
|
||||
expect(myGraph.getEdge(1, 2)).toBeFalsy();
|
||||
|
||||
myGraph.addEdge(new MyEdge(3, 1, 3, 'edge-data-3-1'));
|
||||
myGraph.addEdge(3, 1, 3, 'edge-data-3-1');
|
||||
|
||||
myGraph.addEdge(new MyEdge(1, 9, 19, 'edge-data1-9'));
|
||||
myGraph.addEdge(new MyEdge(9, 7, 97, 'edge-data9-7'));
|
||||
myGraph.addEdge(1, 9, 19, 'edge-data1-9');
|
||||
|
||||
myGraph.addEdge(new MyEdge(7, 9, 79, 'edge-data7-9'));
|
||||
myGraph.addEdge(9, 7, 97, 'edge-data9-7');
|
||||
|
||||
myGraph.addEdge(new MyEdge(1, 4, 14, 'edge-data1-4'));
|
||||
myGraph.addEdge(7, 9, 79, 'edge-data7-9');
|
||||
|
||||
myGraph.addEdge(new MyEdge(4, 7, 47, 'edge-data4-7'));
|
||||
myGraph.addEdge(1, 4, 14, 'edge-data1-4');
|
||||
|
||||
myGraph.addEdge(new MyEdge(1, 2, 12, 'edge-data1-2'));
|
||||
myGraph.addEdge(4, 7, 47, 'edge-data4-7');
|
||||
|
||||
myGraph.addEdge(new MyEdge(2, 3, 23, 'edge-data2-3'));
|
||||
myGraph.addEdge(1, 2, 12, 'edge-data1-2');
|
||||
|
||||
myGraph.addEdge(new MyEdge(3, 5, 35, 'edge-data3-5'));
|
||||
myGraph.addEdge(2, 3, 23, 'edge-data2-3');
|
||||
|
||||
myGraph.addEdge(new MyEdge(5, 7, 57, 'edge-data5-7'));
|
||||
myGraph.addEdge(3, 5, 35, 'edge-data3-5');
|
||||
|
||||
myGraph.addEdge(5, 7, 57, 'edge-data5-7');
|
||||
|
||||
myGraph.addEdge(new MyEdge(7, 3, 73, 'edge-data7-3'));
|
||||
const topologicalSorted = myGraph.topologicalSort();
|
||||
|
|
Loading…
Reference in a new issue