数据结构和算法

开题两点

1.数据结构和算法是前端代码编写很重要也很容易被忽视的地方,所以很想分享一下数据结构和算法相关的东西

2.深度优先搜索和广度优先搜索是两种应用在图上的基础搜索。项目中用到图这种数据结构比较少,用到最多的数据结构是数组和对象,有一种没有根节点的类多叉树的数据结构,在项目中会经常遇到,这里就称为数组对象,我们一般都是通过递归来查找一些相关数据,很少使用其他方式。所以下面我们就来聊一下经典算法之深度优先搜索和广度优先搜索在数组对象中的应用。

深度优先搜索(Depth-First-Search)

简称:DFS

属于一种盲目搜索。深度优先搜索包括从一条路径的起始顶点开始追溯,直到到达最后一个顶点,然后回溯,继续追溯下一条路径,直到到达最后的顶点。如此往复,直到没有路径为止。

特点:

  • js 中最常用递归来实现深度优先搜索,由于易于编写,所以应用特别广泛。
  • 深度搜索的过程可以理解为抽象栈,是后进先出的一个过程。
  • 深度优先搜索算法可以产生目标图的相应拓扑排序表,利用拓扑排序表可以方便的解决很多相关的图论问题,如最大路径问题等等。
存在的问题:

递归导致栈太深,容易爆栈

示例:递归调用:
const dfsByRecursion = function (array, target, params = {}) {
  if (!array || !array.length) return

  let {id = 'id', label = 'label', children = 'children'} = params
  let result

  for (let item of array) {
    if (item[id] === target) {
      return item[label]
    } else if (item[children]) {
      result = dfsByRecursion(item[children], target, {id, label, children})
      if (result) {
        return result
      }
    }
  }
}
示例:非递归调用:
const dfsByWhile = function (array, target, params = {}) {
  if (!array || !array.length) return
  
  let {id = 'id', label = 'label', children = 'children'} = params
  let stack = []
  for (let item of array) {
    stack.push(item)
  }
  let result
  while (stack.length) {
    result = stack.shift()
    if (result[id] === target) {
       return result 
    } else if (result[children] && result[children].length) {
      // 加入栈顶
      stack = [...result[children], ...stack]
    }
  }
} 

广度优先搜索 (Breadth-First-Search)

简称:BFS

BFS也是一种盲目搜索,广度优先搜索从第一个顶点开始,尝试访问尽可能靠近它的顶点。本质上,这种搜索再图上是逐层移动的,首先检查最靠近第一个顶点的层,再逐渐的向下移动到离起始顶点最远的层。过程如下图

特点:

  • 抽象队列,入队出队

  • 主要用于求最短路径等问题

示例代码
const bfsByWhile = function (array, target, params = {}) {
  if (!array || !array.length) return
  
  let {id = 'id', label = 'label', children = 'children'} = params
  let list = []
  for (let item of array) {
    list.push(item)
  }
  let result
  while (list.length) {
    result = list.shift()
    if (result[id] === target) {
       return result
    } else if (result[children] && result[children].length) {
      // 加入队尾
      list = [...list, ...result[children]]
    }
  }
} 

应用举例和思考:

1.vue中vnode的patch过程使用了哪种算法 ?

2.产品内哪些递归可转化为广度优先 ?

3.其他什么例子

总结

本次分享的代码为示例代码,在项目中使用时,可根据实际情况进项优化处理。以后再遇到搜索相关的时候,能打开一个思路,不要只有递归。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值