js算法: 图的两种表示方法以及广度优先算法

图分为有向图和无向图,图的表示方法有两种,且都可以表示有向图或者无向图:

  1. 邻接链表标示
  2. 矩阵标示

如下图:

输入图片说明

使用邻接链表标示:

北京->武汉
武汉->西安->上海
西安
上海->北京
拉萨->北京->西安

使用矩阵标示 [北京, 武汉, 上海, 西安, 拉萨]分别为 v1-v4, 1标示连通, 0标示不连通

| 0 | 1 | 0 | 0 | 0 |
| 0 | 0 | 1 | 1 | 0 |
| 1 | 0 | 0 | 0 | 0 |
| 0 | 0 | 0 | 0 | 0 |
| 1 | 0 | 0 | 1 | 0 |

使用矩阵的优点,很容易看出是否两个结点间的连通性,缺点是牺牲了存储空间

图广度优先算法,找出s源节点出发,经过最少结点到达所有结点算法:

//我们这里采用邻接链表标示图
class Graph {

  constructor(vertexs) {
    this.adj = {};
    vertexs.forEach( (vertex) => {
      this.adj[vertex] = {};
    })
  }

  addVertex(vertex) {    //添加结点
    this.adj[vertex] = {};
  }

  /**
   * @param {Edge} edge
   */
  addEdge(edge) {    //添加边
    if (!this.adj[edge.from]) {
      throw new Error(`vertex ${edge.from} 不存在`)
    }
    if (!this.adj[edge.to]) {
      throw new Error(`vertex ${edge.to} 不存在`)
    }
    this.adj[edge.from][edge.to] = edge.weight;
  }

  neighbor(vertex) {    //结点vertex所有邻居结点
    if (!this.adj[vertex]) {
      throw new Error(`vertex ${vertex} 不存在`);
    }
    return Object.keys(this.adj[vertex]);
  }

  vertexs() {    //获取所有顶点
    return Object.keys(this.adj);
  }

}

class Edge {
  constructor(from, to, weight) {
    this.from = from;
    this.to = to;
    this.weight = weight;
  }
}

var graph = new Graph(['北京', '上海', '武汉', '西安', '拉萨']);
graph.addEdge(new Edge('北京', '武汉', 1));
graph.addEdge(new Edge('武汉', '上海', 1));
graph.addEdge(new Edge('武汉', '西安', 1));
graph.addEdge(new Edge('上海', '北京', 1));
graph.addEdge(new Edge('拉萨', '西安', 1));
graph.addEdge(new Edge('拉萨', '北京', 1));

/**
 * 算法逻辑: 最开始时先把所有结点标为白色,每次把将要遍历的结点染为灰色,
 * 遍历过的结点染为 黑色,当所有结点都为黑色时,遍历完成
 * @param {Graph} graph
 * @param {vertex} s
 * @constructor
 */
function BFS(graph, s) {
  var COLOR_WHITE = 'white';
  var COLOR_GRAY = 'gray';
  var COLOR_BLACK = 'black';

  var vertexs = {}; //临时变量存储所有结点
  //把所有结点设为白色
  graph.vertexs().forEach( (vertex) => {
    vertexs[vertex] = {};
    vertexs[vertex].color = COLOR_WHITE;
    vertexs[vertex].distance = Number.POSITIVE_INFINITY;
    vertexs[vertex].parent = null;
  });
  
  //从源节点s开始遍历
  vertexs[s].color = COLOR_GRAY;
  vertexs[s].distance = 0;    //离源节点的距离
  var queue = [];    //充当先进先出队列
  queue.push(s);
  while(queue.length) {
    let u = queue.shift(); //出列
    graph.neighbor(u).forEach( (vertex) => {
      if (vertexs[vertex].color == COLOR_WHITE) {
        vertexs[vertex].color = COLOR_GRAY;  //开始遍历染成灰色
        vertexs[vertex].parent = u;
        vertexs[vertex].distance = 0; //初始化距离参数,否则为正无穷
        vertexs[vertex].distance = vertexs[u].distance + 1;
        queue.push(vertex);  //入列
      }
    })
    vertexs[u].color = COLOR_BLACK;    //所有子结点及自己遍历完成,染成黑色
  }
  return vertexs;
}

//求北京这个结点都所有结点最短距离:
console.info(BFS(graph, '北京'));
最终输出结果:
{ '北京': { color: 'black', distance: 0, parent: null },
  '上海': { color: 'black', distance: 2, parent: '武汉' },
  '武汉': { color: 'black', distance: 1, parent: '北京' },
  '西安': { color: 'black', distance: 2, parent: '武汉' },
  '拉萨': { color: 'white', distance: Infinity, parent: null } }

转载于:https://my.oschina.net/wanglihui/blog/706038

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值