Definition
A graph is a data structure consisting of a set of nodes or vertices and a set of edges that represent connections between those nodes. Graphs can be directed or undirected, while their edges can be assigned numeric weights.
Each node in a graph data structure must have the following properties:
key
: The key of the nodevalue
: The value of the node
Each edge in a graph data structure must have the following properties:
a
: The starting node of the edgeb
: The target node of the edgeweight
: An optional numeric weight value for the edge
The main operations of a graph data structure are:
addNode
: Inserts a new node with the specific key and valueaddEdge
: Inserts a new edge between two given nodes, optionally setting its weightremoveNode
: Removes the node with the specified keyremoveEdge
: Removes the edge between two given nodesfindNode
: Retrieves the node with the given keyhasEdge
: Checks if the graph has an edge between two given nodessetEdgeWeight
: Sets the weight of a given edgegetEdgeWeight
: Gets the weight of a given edgeadjacent
: Finds all nodes for which an edge exists from a given nodeindegree
: Calculates the total number of edges to a given nodeoutdegree
: Calculates the total number of edges from a given node
Implementation
代码实现
class Graph {
constructor(directed = true) {
this.directed = directed;
this.nodes = [];
this.edges = new Map();
}
addNode(key, value = key) {
this.nodes.push({ key, value });
}
addEdge(a, b, weight) {
this.edges.set(JSON.stringify([a, b]), { a, b, weight });
if (!this.directed)
this.edges.set(JSON.stringify([b, a]), { a: b, b: a, weight });
}
removeNode(key) {
this.nodes = this.nodes.filter(n => n.key !== key);
[...this.edges.values()].forEach(({ a, b }) => {
if (a === key || b === key) this.edges.delete(JSON.stringify([a, b]));
});
}
removeEdge(a, b) {
this.edges.delete(JSON.stringify([a, b]));
if (!this.directed) this.edges.delete(JSON.stringify([b, a]));
}
findNode(key) {
return this.nodes.find(x => x.key === key);
}
hasEdge(a, b) {
return this.edges.has(JSON.stringify([a, b]));
}
setEdgeWeight(a, b, weight) {
this.edges.set(JSON.stringify([a, b]), { a, b, weight });
if (!this.directed)
this.edges.set(JSON.stringify([b, a]), { a: b, b: a, weight });
}
getEdgeWeight(a, b) {
return this.edges.get(JSON.stringify([a, b])).weight;
}
adjacent(key) {
return [...this.edges.values()].reduce((acc, { a, b }) => {
if (a === key) acc.push(b);
return acc;
}, []);
}
indegree(key) {
return [...this.edges.values()].reduce((acc, { a, b }) => {
if (b === key) acc++;
return acc;
}, 0);
}
outdegree(key) {
return [...this.edges.values()].reduce((acc, { a, b }) => {
if (a === key) acc++;
return acc;
}, 0);
}
}
-
Create a
class
with aconstructor
that initializes an empty array,nodes
, and aMap
,edges
, for each instance. The optional argument,directed
, specifies if the graph is directed or not. -
Define an
addNode()
method, which usesArray.prototype.push()
to add a new node in thenodes
array. -
Define an
addEdge()
method, which usesMap.prototype.set()
to add a new edge to theedges
Map, usingJSON.stringify()
to produce a unique key. -
Define a
removeNode()
method, which usesArray.prototype.filter()
andMap.prototype.delete()
to remove the given node and any edges connected to it. -
Define a
removeEdge()
method, which usesMap.prototype.delete()
to remove the given edge. -
Define a
findNode()
method, which usesArray.prototype.find()
to return the given node, if any. -
Define a
hasEdge()
method, which usesMap.prototype.has()
andJSON.stringify()
to check if the given edge exists in theedges
Map. -
Define a
setEdgeWeight()
method, which usesMap.prototype.set()
to set the weight of the appropriate edge, whose key is produced byJSON.stringify()
. -
Define a
getEdgeWeight()
method, which usesMap.prototype.get()
to get the eight of the appropriate edge, whose key is produced byJSON.stringify()
. -
Define an
adjacent()
method, which usesMap.prototype.values()
,Array.prototype.reduce()
andArray.prototype.push()
to find all nodes connected to the given node. -
Define an
indegree()
method, which usesMap.prototype.values()
andArray.prototype.reduce()
to count the number of edges to the given node. -
Define an
outdegree()
method, which usesMap.prototype.values()
andArray.prototype.reduce()
to count the number of edges from the given node.
使用样例
const g = new Graph();
g.addNode('a');
g.addNode('b');
g.addNode('c');
g.addNode('d');
g.addEdge('a', 'c');
g.addEdge('b', 'c');
g.addEdge('c', 'b');
g.addEdge('d', 'a');
g.nodes.map(x => x.value); // ['a', 'b', 'c', 'd']
[...g.edges.values()].map(({ a, b }) => `${a} => ${b}`);
// ['a => c', 'b => c', 'c => b', 'd => a']
g.adjacent('c'); // ['b']
g.indegree('c'); // 2
g.outdegree('c'); // 1
g.hasEdge('d', 'a'); // true
g.hasEdge('a', 'd'); // false
g.removeEdge('c', 'b');
[...g.edges.values()].map(({ a, b }) => `${a} => ${b}`);
// ['a => c', 'b => c', 'd => a']
g.removeNode('c');
g.nodes.map(x => x.value); // ['a', 'b', 'd']
[...g.edges.values()].map(({ a, b }) => `${a} => ${b}`);
// ['d => a']
g.setEdgeWeight('d', 'a', 5);
g.getEdgeWeight('d', 'a'); // 5
翻译自:https://www.30secondsofcode.org/js/s/data-structures-graph