js构建二叉树进行数值数组的去重与优化详解


Posted in Javascript onMarch 26, 2018

前言

本文主要介绍了关于js构建二叉树进行数值数组的去重与优化的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧。

常见两层循环实现数组去重

let arr = [11, 12, 13, 9, 8, 7, 0, 1, 2, 2, 5, 7, 11, 11, 7, 6, 4, 5, 2, 2]
let newArr = []
for (let i = 0; i < arr.length; i++) {
 let unique = true
 for (let j = 0; j < newArr.length; j++) {
  if (newArr[j] === arr[i]) {
   unique = false
   break
  }
 }
 if (unique) {
  newArr.push(arr[i])
 }
}
console.log(newArr)

构建二叉树实现去重(仅适用于数值类型的数组)

将先前遍历过的元素,构建成二叉树,树中每个结点都满足:左子结点的值 < 当前结点的值 < 右子结点的值

这样优化了判断元素是否之前出现过的过程

若元素比当前结点大,只需要判断元素是否在结点的右子树中出现过即可

若元素比当前结点小,只需要判断元素是否在结点的左子树中出现过即可

let arr = [0, 1, 2, 2, 5, 7, 11, 7, 6, 4,5, 2, 2]
class Node {
 constructor(value) {
  this.value = value
  this.left = null
  this.right = null
 }
}
class BinaryTree {
 constructor() {
  this.root = null
  this.arr = []
 }

 insert(value) {
  let node = new Node(value)
  if (!this.root) {
   this.root = node
   this.arr.push(value)
   return this.arr
  }
  let current = this.root
  while (true) {
   if (value > current.value) {
    if (current.right) {
     current = current.right
    } else {
     current.right = node
     this.arr.push(value)
     break
    }
   }
   if (value < current.value) {
    if (current.left) {
     current = current.left
    } else {
     current.left = node
     this.arr.push(value)
     break
    }
   }
   if (value === current.value) {
    break
   }
  }
  return this.arr
 }
}

let binaryTree = new BinaryTree()
for (let i = 0; i < arr.length; i++) {
 binaryTree.insert(arr[i])
}
console.log(binaryTree.arr)

优化思路一,记录最大最小值

记录已经插入元素的最大最小值,若比最大元素大,或最小元素小,则直接插入

let arr = [11, 12, 13, 9, 8, 7, 0, 1, 2, 2, 5, 7, 11, 11, 7, 6, 4, 5, 2, 2]
class Node {
 constructor(value) {
  this.value = value
  this.left = null
  this.right = null
 }
}
class BinaryTree {
 constructor() {
  this.root = null
  this.arr = []
  this.max = null
  this.min = null
 }

 insert(value) {
  let node = new Node(value)
  if (!this.root) {
   this.root = node
   this.arr.push(value)
   this.max = value
   this.min = value
   return this.arr
  }
  if (value > this.max) {
   this.arr.push(value)
   this.max = value
   this.findMax().right = node
   return this.arr
  }
  if (value < this.min) {
   this.arr.push(value)
   this.min = value
   this.findMin().left = node
   return this.arr
  }
  let current = this.root
  while (true) {
   if (value > current.value) {
    if (current.right) {
     current = current.right
    } else {
     current.right = node
     this.arr.push(value)
     break
    }
   }
   if (value < current.value) {
    if (current.left) {
     current = current.left
    } else {
     current.left = node
     this.arr.push(value)
     break
    }
   }
   if (value === current.value) {
    break
   }
  }
  return this.arr
 }

 findMax() {
  let current = this.root
  while (current.right) {
   current = current.right
  }
  return current
 }

 findMin() {
  let current = this.root
  while (current.left) {
   current = current.left
  }
  return current
 }
}

let binaryTree = new BinaryTree()
for (let i = 0; i < arr.length; i++) {
 binaryTree.insert(arr[i])
}
console.log(binaryTree.arr)

优化思路二,构建红黑树

构建红黑树,平衡树的高度

有关红黑树的部分,请见红黑树的插入

let arr = [11, 12, 13, 9, 8, 7, 0, 1, 2, 2, 5, 7, 11, 11, 7, 6, 4, 5, 2, 2]
console.log(Array.from(new Set(arr)))

class Node {
 constructor(value) {
  this.value = value
  this.left = null
  this.right = null
  this.parent = null
  this.color = 'red'
 }
}

class RedBlackTree {
 constructor() {
  this.root = null
  this.arr = []
 }

 insert(value) {
  let node = new Node(value)
  if (!this.root) {
   node.color = 'black'
   this.root = node
   this.arr.push(value)
   return this
  }
  let cur = this.root
  let inserted = false
  while (true) {
   if (value > cur.value) {
    if (cur.right) {
     cur = cur.right
    } else {
     cur.right = node
     this.arr.push(value)
     node.parent = cur
     inserted = true
     break
    }
   }

   if (value < cur.value) {
    if (cur.left) {
     cur = cur.left
    } else {
     cur.left = node
     this.arr.push(value)
     node.parent = cur
     inserted = true
     break
    }
   }

   if (value === cur.value) {
    break
   }
  }
  // 调整树的结构
  if(inserted){
   this.fixTree(node)
  }
  return this
 }

 fixTree(node) {
  if (!node.parent) {
   node.color = 'black'
   this.root = node
   return
  }
  if (node.parent.color === 'black') {
   return
  }
  let son = node
  let father = node.parent
  let grandFather = father.parent
  let directionFtoG = father === grandFather.left ? 'left' : 'right'
  let uncle = grandFather[directionFtoG === 'left' ? 'right' : 'left']
  let directionStoF = son === father.left ? 'left' : 'right'
  if (!uncle || uncle.color === 'black') {
   if (directionFtoG === directionStoF) {
    if (grandFather.parent) {
     grandFather.parent[grandFather.parent.left === grandFather ? 'left' : 'right'] = father
     father.parent = grandFather.parent
    } else {
     this.root = father
     father.parent = null
    }
    father.color = 'black'
    grandFather.color = 'red'

    father[father.left === son ? 'right' : 'left'] && (father[father.left === son ? 'right' : 'left'].parent = grandFather)
    grandFather[grandFather.left === father ? 'left' : 'right'] = father[father.left === son ? 'right' : 'left']

    father[father.left === son ? 'right' : 'left'] = grandFather
    grandFather.parent = father
    return
   } else {
    grandFather[directionFtoG] = son
    son.parent = grandFather

    son[directionFtoG] && (son[directionFtoG].parent = father)
    father[directionStoF] = son[directionFtoG]

    father.parent = son
    son[directionFtoG] = father
    this.fixTree(father)
   }
  } else {
   father.color = 'black'
   uncle.color = 'black'
   grandFather.color = 'red'
   this.fixTree(grandFather)
  }
 }
}

let redBlackTree = new RedBlackTree()
for (let i = 0; i < arr.length; i++) {
 redBlackTree.insert(arr[i])
}
console.log(redBlackTree.arr)

其他去重方法

通过 Set 对象去重

[...new Set(arr)]

通过 sort() + reduce() 方法去重

排序后比较相邻元素是否相同,若不同则添加至返回的数组中

值得注意的是,排序的时候,默认 compare(2, '2') 返回 0;而 reduce() 时,进行全等比较

let arr = [0, 1, 2, '2', 2, 5, 7, 11, 7, 5, 2, '2', 2]
let newArr = []
arr.sort((a, b) => {
 let res = a - b
 if (res !== 0) {
  return res
 } else {
  if (a === b) {
   return 0
  } else {
   if (typeof a === 'number') {
    return -1
   } else {
    return 1
   }
  }
 }
}).reduce((pre, cur) => {
 if (pre !== cur) {
  newArr.push(cur)
  return cur
 }
 return pre
}, null)

通过 includes() + map() 方法去重

let arr = [0, 1, 2, '2', 2, 5, 7, 11, 7, 5, 2, '2', 2]
let newArr = []
arr.map(a => !newArr.includes(a) && newArr.push(a))

通过 includes() + reduce() 方法去重

let arr = [0, 1, 2, '2', 2, 5, 7, 11, 7, 5, 2, '2', 2]
let newArr = arr.reduce((pre, cur) => {
  !pre.includes(cur) && pre.push(cur)
  return pre
}, [])

通过对象的键值对 + JSON 对象方法去重

let arr = [0, 1, 2, '2', 2, 5, 7, 11, 7, 5, 2, '2', 2]
let obj = {}
arr.map(a => {
  if(!obj[JSON.stringify(a)]){
    obj[JSON.stringify(a)] = 1
  }
})
console.log(Object.keys(obj).map(a => JSON.parse(a)))

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

Javascript 相关文章推荐
jquery实现奇偶行赋值不同css值
Feb 17 Javascript
js replace 与replaceall实例用法详解
Aug 03 Javascript
js动态改变select选择变更option的index值示例
Jul 10 Javascript
JavaScript中的ArrayBuffer详细介绍
Dec 08 Javascript
JavaScript结合AJAX_stream实现流式显示
Jan 08 Javascript
JS实现超简单的鼠标拖动效果
Nov 02 Javascript
jQuery实现给input绑定回车事件的方法
Feb 09 Javascript
js中的触发事件对象event.srcElement与event.target详解
Mar 15 Javascript
vue element upload实现图片本地预览
Aug 20 Javascript
解决vue cli使用typescript后打包巨慢的问题
Sep 30 Javascript
详解为什么Vue中不要用index作为key(diff算法)
Apr 04 Javascript
OpenLayer学习之自定义测量控件
Sep 28 Javascript
红黑树的插入详解及Javascript实现方法示例
Mar 26 #Javascript
js+canvas实现滑动拼图验证码功能
Mar 26 #Javascript
JS从非数组对象转数组的方法小结
Mar 26 #Javascript
深入理解Node module模块
Mar 26 #Javascript
利用Console来Debug的10个高级技巧汇总
Mar 26 #Javascript
关于vuejs中v-if和v-show的区别及v-show不起作用问题
Mar 26 #Javascript
vue中使用iview自定义验证关键词输入框问题及解决方法
Mar 26 #Javascript
You might like
php二维数组排序与默认自然排序的方法介绍
2013/04/27 PHP
5种PHP创建数组的实例代码分享
2014/01/17 PHP
destoon利用Rewrite规则设置网站安全
2014/06/21 PHP
微信公众平台实现获取用户OpenID的方法
2015/04/15 PHP
jquery ajax提交表单数据的两种实现方法
2010/04/29 Javascript
javascrip客户端验证文件大小及文件类型并重置上传
2011/01/12 Javascript
jQuery实现带延迟的二级tab切换下拉列表效果
2015/09/01 Javascript
jquery对象和DOM对象的任意相互转换
2016/02/21 Javascript
jQuery数据检索中根据关键字快速定位GridView指定行的实现方法
2016/06/08 Javascript
利用Vue.js实现checkbox的全选反选效果
2017/01/18 Javascript
Vue数据监听方法watch的使用
2018/03/28 Javascript
JavaScript中的回调函数实例讲解
2019/01/27 Javascript
ES6基础之展开语法(Spread syntax)
2019/02/21 Javascript
vue实现百度下拉列表交互操作示例
2019/03/12 Javascript
详解vue 自定义marquee无缝滚动组件
2019/04/09 Javascript
详解Vue-cli3.X使用px2rem遇到的问题
2019/08/09 Javascript
layui加载表格,绑定新增,编辑删除,查看按钮事件的例子
2019/09/06 Javascript
在Python中使用异步Socket编程性能测试
2014/06/25 Python
如何用Python制作微信好友个性签名词云图
2019/06/28 Python
使用PyTorch训练一个图像分类器实例
2020/01/08 Python
python GUI库图形界面开发之PyQt5控件数据拖曳Drag与Drop详细使用方法与实例
2020/02/27 Python
使用python客户端访问impala的操作方式
2020/03/28 Python
Keras框架中的epoch、bacth、batch size、iteration使用介绍
2020/06/10 Python
python3中TQDM库安装及使用详解
2020/11/18 Python
css3实现椭圆轨迹旋转的示例代码
2018/10/29 HTML / CSS
如何在Canvas上的图形/图像绑定事件监听的实现
2020/09/16 HTML / CSS
SEPHORA新西兰官方网站:购买化妆品和护肤品
2016/12/02 全球购物
后勤人员自我评价怎么写
2013/09/19 职场文书
12月小学生校园广播稿
2014/02/04 职场文书
工作违纪检讨书
2014/02/17 职场文书
公司党的群众路线教育实践活动领导班子对照检查材料
2014/09/25 职场文书
班子个人四风问题整改措施
2014/10/04 职场文书
先进个人评语大全
2015/01/04 职场文书
2016年小学生新年寄语
2015/08/18 职场文书
2016党风廉政建设心得体会范文
2016/01/25 职场文书
导游词之山东八大关
2019/12/18 职场文书