降维打击!为什么我认为数据结构与算法对前端开发很重要 (2)

还好 keys 的长度只有 3 ,这种东西长了根本没办法写,很明显可以看出来这里面有重复的部分,可以通过循环搞定,但是想了很久都没有思路,就搁置了。

后来,有一天晚饭后不是很忙,就跟旁边做数据的同事聊了一下这个需求,请教一下该怎么用循环来处理。他看了一下,就问我:“你知道 trie 树吗?”。我头一次听到这个概念,他简单的给我讲了一下,然后说感觉处理的问题有些类似,让我可以研究一下 trie 树的原理并试着优化一下。

讲道理, trie 树这个数据结构网上确实有很多资料,但很少有使用 JavaScript 实现的,不过原理倒是不难。尝试之后,我就将 transObject 的代码优化成了这样。(关于 trie 树,还请读者自己阅读相关材料)

var transObject = function(tableData, keys) {
  let hashTable = {}, res = []
  for (let i = 0; i < tableData.length; i++) {
    let arr = res, cur = hashTable
    for (let j = 0; j < keys.length; j++) {
      let key = keys[j], filed = tableData[i][key]
      if (!cur[filed]) {
        let pusher = {
          value: filed
        }, tmp
        if (j !== (keys.length - 1)) {
          tmp = []
          pusher.children = tmp
        }
        cur[filed] = { $$pos: arr.push(pusher) - 1 }
        cur = cur[filed]
        arr = tmp
      } else {
        cur = cur[filed]
        arr = arr[cur.$$pos].children
      }
    }
  }
  return res
}

这样,解决方案就和 keys 的长短无关了。

这种解决方案正如《三体》里面使用「二向箔」对宇宙文明进行降维打击一般干净利落!

降维打击!为什么我认为数据结构与算法对前端开发很重要

如果你对「Trie」树的相关概念不了解的话,可以继续往下查看进行阅读学习。

这是之前的写的一篇旧文,小吴这里进行了一定的修改和排版

Trie树

Trie 这个名字取自“retrieval”,检索,因为 Trie 可以只用一个前缀便可以在一部字典中找到想要的单词。
虽然发音与「Tree」一致,但为了将这种 字典树 与 普通二叉树 以示区别,程序员小吴一般读「Trie」尾部会重读一声,可以理解为读「TreeE」。

Trie 树,也叫“字典树”。顾名思义,它是一个树形结构。它是一种专门处理字符串匹配的数据结构,用来解决在一组字符串集合中快速查找某个字符串的问题。

此外 Trie 树也称前缀树(因为某节点的后代存在共同的前缀,比如 pan 是 panda 的前缀)。

它的key都为字符串,能做到高效查询和插入,时间复杂度为 O(k),k 为字符串长度,缺点是如果大量字符串没有共同前缀时很耗内存。

它的核心思想就是通过最大限度地减少无谓的字符串比较,使得查询高效率,即「用空间换时间」,再利用共同前缀来提高查询效率。

Trie树的特点

假设有 5 个字符串,它们分别是:code,cook,five,file,fat。现在需要在里面多次查找某个字符串是否存在。如果每次查找,都是拿要查找的字符串跟这 5 个字符串依次进行字符串匹配,那效率就比较低,有没有更高效的方法呢?

如果将这 5 个字符串组织成下图的结构,从肉眼上扫描过去感官上是不是比查找起来会更加迅速。

Trie树样子

Trie树样子

通过上图,可以发现 Trie树 的三个特点:

根节点不包含字符,除根节点外每一个节点都只包含一个字符

从根节点到某一节点,路径上经过的字符连接起来,为该节点对应的字符串

每个节点的所有子节点包含的字符都不相同

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpwzxy.html