数据结构与算法 【图】

119 阅读3分钟

定义

图是一种数据结构,由一组节点或顶点以及一组表示这些节点之间连接的边组成。

图可以是有向的或无向的,而它们的边可以分配数字代表权重。

图数据结构中的每个节点都必须具有以下属性:

  • key: 节点的键
  • value: 节点的值

图数据结构中的每条边都必须具有以下属性:

  • a: 边的起始节点

  • b: 边的目标节点

  • weight:边缘

图数据结构的主要操作是:

  • addNode:插入具有特定键和值的新节点

  • addEdge:在两个给定节点之间插入一条新边,可选择设置其权重

  • removeNode:删除具有指定键的节点

  • removeEdge:删除两个给定节点之间的边

  • findNode:检索具有给定键的节点

  • hasEdge: 检查图在两个给定节点之间是否有边

  • setEdgeWeight: 设置给定边的权重

  • getEdgeWeight: 获取给定边的权重

  • adjacent:从给定节点查找存在边的所有节点

  • indegree:计算给定节点的总边数

  • outdegree:计

    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); } }

  • class使用 a为每个实例constructor初始化一个空数组 ,nodes和 a Map,创建 a 。edges可选参数directed指定图是否有向。

  • 定义一个addNode()方法,用于Array.prototype.push()在nodes数组中添加一个新节点。

  • 定义一个addEdge()方法,用于Map.prototype.set()向edgesMap 添加新边,JSON.stringify()用于生成唯一键。

  • 定义一个removeNode()方法,该方法使用Array.prototype.filter()Map.prototype.delete()删除给定的节点和任何连接到它的边。

  • 定义一个removeEdge()方法,用于Map.prototype.delete()移除给定的边。

  • 定义一个findNode()方法,用于Array.prototype.find()返回给定节点(如果有)。

  • 定义一个hasEdge()方法,该方法使用Map.prototype.has()JSON.stringify()检查给定的边是否存在于edges地图中。

  • 定义一个setEdgeWeight()方法,用于Map.prototype.set()设置适当边的权重,其密钥由 生成JSON.stringify()

  • 定义一个getEdgeWeight()方法,用于Map.prototype.get()获取相应边的 8 个,其密钥由 生成JSON.stringify()

  • 定义一个adjacent()方法,该方法使用和Map.prototype.values()查找连接到给定节点的所有节点。Array.prototype.reduce()Array.prototype.push()

  • 定义一个indegree()方法,该方法使用Map.prototype.values()Array.prototype.reduce()计算给定节点的边数。

  • 定义一个outdegree()方法,该方法使用Map.prototype.values()Array.prototype.reduce()计算给定节点的边数。

    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