js实现数据结构及算法之图和图算法(Graphs)

本文介绍了图的基本概念,包括顶点、边、路径、环等,并详细解释了有向图与无向图的区别。此外,还探讨了图的两种主要遍历算法:广度优先搜索(BFS)与深度优先搜索(DFS),并提供了JavaScript实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

图(Graphs)

图由边的集合及顶点的集合组成,每个城市就是一个顶点,每一条道路就是一个边

顶点也有权重,也称为成本。如果一个图的顶点对是有序的,则称之为有向图。在对有向图中的顶点排序后,便可以在两个顶点之间绘制一个箭头。有向图表明了顶点的流向。流程图就是一个有向图的例子

如果图是无序的,则称之为无序图或无向图

从一个节点走到另一个节点的这一组边称为路径。路径中所有的顶点都由边连接。路径的长度用路径中第一个顶点到最后一个顶点之间边的数量表示,指向自身的顶点组成的路径称为,环的长度为0

圈是至少有一条边的路径,且路径的第一个顶点和最后一个顶点相同。无论有向图还是无向图只要是没有重复的顶点的圈就是一个简单圈,除了第一个和最后一个顶点以外,路径的其他顶点有重复的圈称为平凡圈

如果两个顶点之间有路径,那么这两个顶点之间就是强连通的,如果有向图的所有顶点都是强连通的,那么这个有向图也是强连通的

图的遍历

广度优先搜索(BFS)

从第一个顶点开始,尝试访问尽可能靠近它的顶点

深度优先搜索(DFS)

访问一个没有访问过的顶点,将他标记为已访问,再递归地去访问在初始顶点的邻接表中其他没有访问过的顶点

js实现

/**
 * 一个简单的图和图算法
 * @constructor
 */
function Graph(v) {
  this.vertices = v    //顶点
  this.edges = 0       //边
  this.adj = []          //定义数组
  this.marked = []  //标记是否已访问 false为未访问 true为访问过了
  for (var i = 0; i < this.vertices; i++) {           //定义二维数组
    this.adj[i] = []
    this.marked[i] = false
  }
  this.addEdge = addEdge  //添加顶点
  this.show = show  //显示顶点
  this.dfs = dfs      //深度优先搜索
  this.bfs = bfs      //广度优先搜索
  this.edgeTo = []  //从一个顶点到下一个顶点的所有边
  this.hasPathTo = hasPathTo //是否有路径
  this.pathTo = pathTo //最短路径
}

//添加顶点
function addEdge(v, m) {
  this.adj[v].push(m)
  this.adj[m].push(v)
  this.edges++
}

//显示顶点
function show() {
  for (var i = 0; i < this.vertices; i++) {
    var edges = ''
    for (var j = 0; j < this.vertices; j++) {
      if (this.adj[i][j]) {
        edges += this.adj[i][j] + ' '
      }
    }
    console.log(i + '->' + edges)
  }
}

//深度优先搜索
function dfs(v) {
  this.marked[v] = true
  if (this.adj[v] !== undefined) {
    console.log(v + '该节点被访问了')
  }
  for (var w in this.adj[v]) {
    var current = this.adj[v][w]
    if (!this.marked[current]) {
      this.dfs(current)
    }
  }
}

//广度优先搜索
function bfs(v) {
  var queue = []
  this.marked[v] = true
  queue.push(v)
  while (queue.length > 0) {
    var s = queue.shift()
    if (s !== undefined) {
      console.log(s + '该节点被访问了')
    }
    for (var w in this.adj[s]) {
      var current = this.adj[s][w]
      if (!this.marked[current]) {
        this.marked[current] = true
        this.edgeTo[current] = s
        queue.push(current)
      }
    }
  }
}

//是否有路径
function hasPathTo(v) {
  return this.marked[v]
}
//最短路径
function pathTo(v) {
  var source = 0
  if(!this.hasPathTo(v)) return undefined
  var path =[]
  for(var i=v; i!=source;i=this.edgeTo[i]) {
    path.push(i)
  }
  path.push(source)
  return path
}

var graph = new Graph(6)
graph.addEdge(0, 1)
graph.addEdge(0, 2)
graph.addEdge(2, 4)
graph.addEdge(1, 3)
graph.addEdge(3, 4)
graph.addEdge(3, 5)
graph.addEdge(4, 5)
graph.show()
console.log('=======深度优先搜索=========')
// graph.dfs(0)
console.log('=======广度优先搜索=========')
graph.bfs(0)
var paths = graph.pathTo(5)
var str = ''
while(paths.length>0){
  if(paths.length>1) {
    str += paths.pop()+'->'
  }else {
    str +=paths.pop()
  }
}
console.log(str)复制代码


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值