当前位置:   article > 正文

数据结构——二叉树_二叉树的根算不算叶子

二叉树的根算不算叶子

树形结构:有向无环图 树是图的一种

树形结构有一个根节点

没有回路

根节点:A

叶子节点:下面没有其他节点

节点:既不是根节点,也不是叶子节点的 普通节点

树的度:树 中有最多叉的节点有多少个插叉,这棵树的度就为多少

树的深度:树最深有几层 深度就为几

二叉树:

树的度最多为2的树形结构

满二叉树:

  • 所有叶子节点都在最底层
  • 每个风叶子节点都有两个子节点

完全二叉树:

国内定义:

  • 叶子节点都在最后一层或倒数第二层
  • 叶子节点都向左聚拢

国际定义:

  • 叶子节点都在最后一层或倒数第二层
  • 如果有叶子节点,则必然有两个叶子节点

 在二叉树中,每个节点都认为自己是根节点

子树:二叉树中,每一个节点或叶子节点,都是一棵子树的根节点

左子树、右子树:

传递二叉树要传根节点

树的遍历

前序遍历:先根次序遍历  前->左->右 前:当前

中序遍历:先根次序遍历 左->前->右

后序遍历:先根次序遍历 左->右->前

先构建一个树

  1. function Node (value) {
  2. this.value = value
  3. this.left = null
  4. this.right = null
  5. }
  6. var a = new Node('a')
  7. var b = new Node('b')
  8. var c = new Node('c')
  9. var d = new Node('d')
  10. var e = new Node('e')
  11. var f = new Node('f')
  12. var g = new Node('g')
  13. a.left = c
  14. a.right = b
  15. b.left = d
  16. b.right = e
  17. c.left = f
  18. c.right = g

1.前序遍历

  1. function getTree (node) {
  2. if (node == null) return
  3. console.log(node.value)
  4. getTree(node.left)
  5. getTree(node.right)
  6. }
  7. getTree(a)

2.中序遍历

  1. function getTree (node) {
  2. if (node == null) return
  3. getTree(node.left)
  4. console.log(node.value)
  5. getTree(node.right)
  6. }
  7. getTree(a)

3.后序遍历

  1. function getTree (node) {
  2. if (node == null) return
  3. getTree(node.left)
  4. getTree(node.right)
  5. console.log(node.value)
  6. }
  7. getTree(a)

二叉树的还原

准备一下,前序、中序、后续遍历数组,以及创建树节点函数

  1. function changeToLowerCase (item) {
  2. return Array.from(item).map(o => o.toLowerCase())
  3. }
  4. //懒得写小写数组了,转换了一下,可直接代入原始小写数组哦
  5. var arr1 = changeToLowerCase('ACFGBDE')//arr1 (7) ['a', 'c', 'f', 'g', 'b', 'd', 'e']
  6. var arr2 = changeToLowerCase('FCGADBE')//arr2 (7) ['f', 'c', 'g', 'a', 'd', 'b', 'e']
  7. var arr3 = changeToLowerCase('FGCDEBA')//arr3 (7) ['f', 'g', 'c', 'd', 'e', 'b', 'a']
  8. function Node (value) {
  9. this.value = value
  10. this.left = null
  11. this.right = null
  12. }

 前序和中序还原一棵二叉树

  1. function restore (arr1, arr2) {
  2. if (arr1 == null || arr2 == null || arr1.length == 0 || arr2.length == 0 || arr1.length !== arr2.length) return null
  3. var root = new Node(arr1[0])//先确定根节点
  4. var index = arr2.indexOf(root.value)//找到根节点在中序遍历数组中的位置索引
  5. var arr1Left = arr1.slice(1, 1 + index)//前序遍历左子树
  6. var arr1Right = arr1.slice(1 + index, arr1.length)//前序遍历右子树
  7. var arr2Left = arr2.slice(0, index)//中序遍历左子树
  8. var arr2Right = arr2.slice(index + 1, arr2.length)//中序遍历右子树
  9. root.left = restore(arr1Left, arr2Left)//根据左子树的前序和中序 还原左子树 并赋值给root.left
  10. root.right = restore(arr1Right, arr2Right)//根据右子树的前序和中序 还原右子树 并赋值给root.right
  11. return root
  12. }
  13. console.log(restore(arr1, arr2))

 中序和后序还原一棵二叉树

  1. function restore (arr2, arr3) {
  2. if (arr3 == null || arr2 == null || arr3.length == 0 || arr2.length == 0 || arr3.length !== arr2.length) return null
  3. var root = new Node(arr3[arr3.length - 1])//先确定根节点
  4. var index = arr2.indexOf(root.value)//找到根节点在后序遍历数组中的位置索引
  5. var arr2Left = arr2.slice(0, index)//中序遍历左子树
  6. var arr2Right = arr2.slice(index + 1, arr2.length)//中序遍历右子树
  7. var arr3Left = arr3.slice(0, index)//后序遍历左子树
  8. var arr3Right = arr3.slice(index, arr3.length - 1)//后序遍历右子树
  9. root.left = restore(arr2Left, arr3Left)//根据左子树的后序和中序 还原左子树 并赋值给root.left
  10. root.right = restore(arr2Right, arr3Right)//根据右子树的后序和中序 还原右子树 并赋值给root.right
  11. return root
  12. }
  13. console.log(restore(arr2, arr3))

 二叉树的搜索

树的搜索、图的搜索、爬虫的逻辑、搜索引擎的爬虫算法

  • 深度优先搜索:更适合探索未知
  • 广度优先搜索:更适合探索局域

1.深度优先搜索

  1. //对于二叉树来说,深度优先搜索 和 前序遍历顺序是一样的
  2. function deepSearch (root, target) {
  3. if (root == null) return false
  4. if (root.value == target) return true
  5. var left = deepSearch(root.left, target)
  6. var right = deepSearch(root.right, target)
  7. return left || right
  8. }
  9. console.log(deepSearch(a, 'd'))//true

2.广度优先搜索

  1. function breadthSearch (rootList, target) {
  2. if (rootList == null || rootList.length == 0) return false
  3. var childList = []//当前层所有节点的子节点,都在这个list中,这样传入下一层级时候,就可以遍历整个层级的集合
  4. for (let i = 0; i < rootList.length; i++) {
  5. console.log(rootList[i])
  6. if (rootList[i] != null && rootList[i].value == target) {
  7. return true
  8. } else {
  9. childList.push(rootList[i].left)
  10. childList.push(rootList[i].right)
  11. }
  12. }
  13. return breadthSearch(childList, target)
  14. }
  15. console.log(breadthSearch([a], 'c'))//true

有点问题,需要改进。如果传入target为“n”,则报错

后续待优化

 3.树的深度优先搜索(多叉)

深度遍历 

  1. function Node (value) {
  2. this.value = value
  3. this.childs = []
  4. }
  5. var a = new Node('a')
  6. var b = new Node('b')
  7. var c = new Node('c')
  8. var d = new Node('d')
  9. var e = new Node('e')
  10. var f = new Node('f')
  11. a.childs.push(c)
  12. a.childs.push(b)
  13. a.childs.push(f)
  14. b.childs.push(e)
  15. b.childs.push(d)
  16. function deepSearch (root) {
  17. if (root == null) return
  18. // console.log(root.childs)
  19. console.log(root.value)
  20. for (let i = 0; i < root.childs.length; i++) {
  21. deepSearch(root.childs[i])
  22. }
  23. }
  24. deepSearch(a)

深度搜索 

  1. function deepSearch (root, target) {
  2. if (root == null) return false
  3. if (root.value == target) return true
  4. var result = false
  5. for (let i = 0; i < root.childs.length; i++) {
  6. result = deepSearch(root.childs[i], target)
  7. }
  8. return result
  9. }
  10. deepSearch(a, 'c')//true

4.树的广度优先搜索(多叉)

还是用上面那个多叉的图 广度搜索

  1. function Node (value) {
  2. this.value = value
  3. this.childs = []
  4. }
  5. var a = new Node('a')
  6. var b = new Node('b')
  7. var c = new Node('c')
  8. var d = new Node('d')
  9. var e = new Node('e')
  10. var f = new Node('f')
  11. a.childs.push(c)
  12. a.childs.push(b)
  13. a.childs.push(f)
  14. b.childs.push(e)
  15. b.childs.push(d)
  16. function bfs (root, target) {
  17. if (root == null || root.length == 0) {
  18. return false
  19. }
  20. var childs = []
  21. for (let i = 0; i < root.length; i++) {
  22. if (root[i].value == target) {
  23. return true
  24. }
  25. childs = childs.concat(root[i].childs)
  26. }
  27. return bfs(childs, target)
  28. }
  29. console.log(bfs([a], 'b'))//true
  30. console.log(bfs([a], 'n'))//false

二叉树的比较

1.首先准备第二棵树

  1. var a1 = new Node('a')
  2. var b1 = new Node('b')
  3. var c1 = new Node('c')
  4. var d1 = new Node('d')
  5. var e1 = new Node('e')
  6. var f1 = new Node('f')
  7. var g1 = new Node('g')
  8. a1.left = c1
  9. a1.right = b1
  10. b1.left = d1
  11. b1.right = e1
  12. c1.left = f1
  13. c1.right = g1

2. 左右不能互换,左子树与左子树比较、右边和右边比较

  1. function compare (root1, root2) {
  2. if (root1 == root2) return true//是同一棵树
  3. if (root1 == null || root2 == null) return false
  4. if (root1.value != root2.value) return false//相同位置值不相等
  5. var leftBool = compare(root1.left, root2.left)//判断左子树是否相等
  6. var rightBool = compare(root1.right, root2.right)//判断右子树是否相等
  7. return leftBool && rightBool
  8. }
  9. console.log(compare(a, a1))//true

遇到二叉树比较问题时,必须要确定,左右两棵子树如果交换位置,即左右互换,算不算同一棵二叉树

默认互换后不是同一棵

面试时问 确定规则

3.左右交换算同一棵

  1. function compare (root1, root2) {
  2. if (root1 == root2) return true//是同一棵树
  3. if (root1 == null || root2 == null) return false
  4. if (root1.value != root2.value) return false//相同位置值不相等
  5. var leftBool = compare(root1.left, root2.left)//判断左子树是否相等
  6. var rightBool = compare(root1.right, root2.right)//判断右子树是否相等
  7. //左右可互换情况
  8. var leftBool1 = compare(root1.left, root2.right)//判断左子树与右子树是否相等
  9. var rightBool1 = compare(root1.right, root2.left)//判断右子树与左子树是否相等
  10. return leftBool && rightBool || leftBool1 && rightBool1
  11. }
  12. console.log(compare(a, a1))//true

二叉树diff算法

如图所示,比较以下两棵树

1.首先构建要比较的树

  1. var a1 = new Node('a')
  2. var c1 = new Node('c')
  3. var e1 = new Node('e')
  4. var f1 = new Node('f')
  5. var g1 = new Node('g')
  6. var x1 = new Node('x')
  7. var z1 = new Node('z')
  8. a1.left = c1
  9. a1.right = x1
  10. x1.right = e1
  11. c1.left = f1
  12. c1.right = g1
  13. g1.right = z1

 2.diffTree算法

  1. // 新增了什么 修改了什么 删除了什么
  2. var diffList = []
  3. function difftree (root1, root2, diffList) {
  4. if (root1 == root2) return diffList
  5. if (root1 == null && root2 != null) {//新增了节点
  6. diffList.push({ type: '新增', origin: null, now: root2 })
  7. } else if (root1 != null && root2 == null) {//删除了节点
  8. diffList.push({ type: '删除', origin: root1, now: null })
  9. } else if (root1.value != root2.value) {//相同的位置节点值不同,修改了节点
  10. diffList.push({ type: '修改', origin: root1, now: root2 })//修改后也要走diffTree 因为修改当前节点 不代表所有子节点都变了
  11. difftree(root1.left, root2.left, diffList)
  12. difftree(root1.right, root2.right, diffList)
  13. } else {
  14. difftree(root1.left, root2.left, diffList)
  15. difftree(root1.right, root2.right, diffList)
  16. }
  17. return diffList
  18. }
  19. console.log(difftree(a, a1, diffList))

3.最后结果呈现

 白的也一样,那个方便看那个~

 二叉搜索树(二叉排序树) 

首先 这是一棵搜索树

其次 有排序的效果,左子树的节点都比当前节点小,右子树的节点都比当前节点大

  1. //制作一个随机数组
  2. var arr = []
  3. for (let i = 0; i < 10000; i++) {
  4. arr[i] = Math.floor(Math.random() * 10000)
  5. }
  6. var num = 0
  7. function search (arr, target) {
  8. for (let i = 0; i < arr.length; i++) {
  9. num += 1
  10. if (arr[i] == target) return true
  11. }
  12. return false
  13. }
  14. function Node (value) {
  15. this.value = value
  16. this.right = null
  17. this.left = null
  18. }
  19. function addNode (root, num) {
  20. if (root == null) return
  21. if (root.value == num) return
  22. if (root.value < num) {//目标值比当前节点大
  23. if (root.right == null) root.right = new Node(num)//右侧为空 则创建新节点 将目标值放在该位置
  24. else {
  25. addNode(root.right, num)//右侧不为空 则向右侧进行递归
  26. }
  27. } else {//目标值比当前节点小
  28. if (root.left == null) {
  29. root.left = new Node(num)
  30. }
  31. else {
  32. addNode(root.left, num)
  33. }
  34. }
  35. }
  36. function buildSearchTree (arr) {
  37. if (arr == null || arr.length === 0) return null
  38. var root = new Node(arr[0])
  39. for (let i = 1; i < arr.length; i++) {
  40. addNode(root, arr[i])
  41. }
  42. return root
  43. }
  44. var num2 = 0
  45. function searchByTree (root, target) {
  46. if (root == null) return false
  47. num2 += 1
  48. if (root.value == target) return true
  49. if (root.value > target) {
  50. return searchByTree(root.left, target)
  51. } else {
  52. return searchByTree(root.right, target)
  53. }
  54. }
  55. console.log("普通for循环搜索", search(arr, 2344), num)
  56. var root1 = buildSearchTree(arr)
  57. console.log(root1)
  58. console.log("二叉树搜索", searchByTree(root1, 2344), num2)

平衡二叉树

  • 根节点的左子树与右子树的高度差不能超过1
  • 这棵树每个子树都符合第一条

1.二叉树准备工作

  1. function Node (value) {
  2. this.value = value
  3. this.left = null
  4. this.right = null
  5. }
  6. var a = new Node('a')
  7. var b = new Node('b')
  8. var c = new Node('c')
  9. var d = new Node('d')
  10. var e = new Node('e')
  11. var f = new Node('f')
  12. var g = new Node('g')
  13. var h = new Node('F')
  14. var j = new Node('J')
  15. a.left = b
  16. a.right = c
  17. b.left = d
  18. b.right = e
  19. c.left = f
  20. c.right = g
  21. d.right = h
  22. e.right = j

 2.计算左右子树层深 判断是否为平衡二叉树

  1. function getDeep (root) {
  2. if (root == null) return 0
  3. var leftDeep = getDeep(root.left)
  4. var rightDeep = getDeep(root.right)
  5. return Math.max(leftDeep, rightDeep) + 1//算出左右子树层深后再加当前一层
  6. }
  7. function isBalance (root) {
  8. if (root == null) return true
  9. var leftDeep = getDeep(root.left)
  10. var rightDeep = getDeep(root.right)
  11. if (Math.abs(leftDeep - rightDeep) > 1)//绝对值大于1 则不平衡
  12. {
  13. return false
  14. } else {
  15. return isBalance(root.left) && isBalance(root.right)
  16. }
  17. }
  18. console.log(isBalance(a))//false

二叉树的单旋操作(左单旋,右单旋)

某一节点不平衡

1.左单旋

如果左边浅,右边深,进行左单旋

左单旋时

  • 旋转节点:当前不平衡的节点
  • 新根:右子树的根节点
  • 变化分支:旋转节点的右子树的左子树
  • 不变分支:旋转节点的右子树的右子树 

  • 旋转节点:不平衡的节点为旋转节点(2)
  • 新根:旋转之后称为根节点的节点(5)
  • 变化分支:父级节点发生变化的分支(3)
  • 不变分支:父级节点不发生变化的分支(6)

 to do list

  1. 找到新根
  2. 找到变化分支
  3. 当前旋转节点的右孩子为变化分支
  4. 新根的左孩子为旋转节点
  5. 返回新的根节点

2.右单旋

右单旋时

  • 旋转节点:当前不平衡的节点
  • 新根:左子树的根节点
  • 变化分支:旋转节点的左子树的右子树 
  • 不变分支:旋转节点的左子树的左子树

 to do list

  1. 找到新根
  2. 找到变化分支
  3. 当前旋转节点的左孩子为变化分支
  4. 新根的右孩子为旋转节点
  5. 返回新的根节点

3. 左单旋、右单旋后判断是否为平衡二叉树

  1. function Node (value) {
  2. this.value = value
  3. this.left = null
  4. this.right = null
  5. }
  6. var node2 = new Node('2')
  7. var node5 = new Node('5')
  8. var node3 = new Node('3')
  9. var node6 = new Node('6')
  10. node2.right = node5
  11. node5.left = node3
  12. node5.right = node6
  13. function change (root) {
  14. // 返回平衡之后的根节点
  15. if (isBalance(root)) return root
  16. if (root.left != null) root.left = change(root.left)
  17. if (root.right != null) root.right = change(root.right)
  18. var leftDeep = getDeep(root.left)
  19. var rightDeep = getDeep(root.right)
  20. if (Math.abs(leftDeep - rightDeep) < 2) {
  21. return true
  22. } else if (leftDeep > rightDeep) {//不平衡 左边深 右旋
  23. return rightRotate(root)
  24. } else {//不平衡 右边深 左旋
  25. return leftRotate(root)
  26. }
  27. }
  28. function leftRotate (root) {
  29. // 找到新根
  30. var newRoot = root.right
  31. // 找到变化分支
  32. var changeTree = root.right.left
  33. // 当前旋转节点的右孩子为变化分支
  34. root.right = changeTree
  35. // 新根的左孩子为旋转节点
  36. newRoot.left = root
  37. // 返回新的根节点
  38. return newRoot
  39. }
  40. function rightRotate (root) {
  41. // 找到新根
  42. var newRoot = root.left
  43. // 找到变化分支
  44. var changeTree = root.left.right
  45. // 当前旋转节点的左孩子为变化分支
  46. root.left = changeTree
  47. // 新根的右孩子为旋转节点
  48. newRoot.right = root
  49. // 返回新的根节点
  50. return newRoot
  51. }
  52. function getDeep (root) {
  53. if (root == null) return 0
  54. var leftDeep = getDeep(root.left)
  55. var rightDeep = getDeep(root.right)
  56. return Math.max(leftDeep, rightDeep) + 1//算出左右子树层深后再加当前一层
  57. }
  58. function isBalance (root) {
  59. if (root == null) return true
  60. var leftDeep = getDeep(root.left)
  61. var rightDeep = getDeep(root.right)
  62. if (Math.abs(leftDeep - rightDeep) > 1)//绝对值大于1 则不平衡
  63. {
  64. return false
  65. } else {
  66. return isBalance(root.left) && isBalance(root.right)
  67. }
  68. }
  69. console.log("node2是否为平衡二叉树", isBalance(node2))
  70. var newRoot = change(node2)
  71. console.log("新的二叉树是", newRoot)
  72. console.log("新的二叉树是否为平衡二叉树", isBalance(newRoot))

二叉树的双旋

1.左右双旋 右左双旋

当要对某个节点进行左单旋时,如果变化是唯一的最深分支 ,那么我们要对新根进行右单旋  然后再左单旋 这样的旋转叫右左双旋

当要对某个节点进行右单旋时,如果变化是唯一的最深分支,那么我们要对新根进行左单旋 然后 进行右单旋,这样的旋转叫做左右双旋

  • 主要更改在change()函数中
  1. function change (root) {
  2. // 返回平衡之后的根节点
  3. if (isBalance(root)) return root
  4. if (root.left != null) root.left = change(root.left)
  5. if (root.right != null) root.right = change(root.right)
  6. var leftDeep = getDeep(root.left)
  7. var rightDeep = getDeep(root.right)
  8. if (Math.abs(leftDeep - rightDeep) < 2) {
  9. return true
  10. } else if (leftDeep > rightDeep) {//不平衡 左边深 右旋
  11. var changeTreeDeep = getDeep(root.left.right) //获取变化分支深度
  12. var noChangeTreeDeep = getDeep(root.left.left)//获取不变化分支深度
  13. if (changeTreeDeep > noChangeTreeDeep) {
  14. root.left = leftRotate(root.left)
  15. }
  16. return rightRotate(root)
  17. } else {//不平衡 右边深 左旋
  18. var changeTreeDeep = getDeep(root.right.left) //获取变化分支深度
  19. var noChangeTreeDeep = getDeep(root.right.right)//获取不变化分支深度
  20. if (changeTreeDeep > noChangeTreeDeep) {
  21. root.right = rightRotate(root.right)
  22. }
  23. return leftRotate(root)
  24. }
  25. }
  • 整体代码
  1. function Node (value) {
  2. this.value = value
  3. this.left = null
  4. this.right = null
  5. }
  6. var node8 = new Node('8')
  7. var node7 = new Node('7')
  8. var node6 = new Node('6')
  9. var node5 = new Node('5')
  10. var node2 = new Node('2')
  11. node8.left = node7
  12. node7.left = node6
  13. node6.left = node5
  14. node5.left = node2
  15. function change (root) {
  16. // 返回平衡之后的根节点
  17. if (isBalance(root)) return root
  18. if (root.left != null) root.left = change(root.left)
  19. if (root.right != null) root.right = change(root.right)
  20. var leftDeep = getDeep(root.left)
  21. var rightDeep = getDeep(root.right)
  22. if (Math.abs(leftDeep - rightDeep) < 2) {
  23. return true
  24. } else if (leftDeep > rightDeep) {//不平衡 左边深 右旋
  25. var changeTreeDeep = getDeep(root.left.right) //获取变化分支深度
  26. var noChangeTreeDeep = getDeep(root.left.left)//获取不变化分支深度
  27. if (changeTreeDeep > noChangeTreeDeep) {
  28. root.left = leftRotate(root.left)
  29. }
  30. return rightRotate(root)
  31. } else {//不平衡 右边深 左旋
  32. var changeTreeDeep = getDeep(root.right.left) //获取变化分支深度
  33. var noChangeTreeDeep = getDeep(root.right.right)//获取不变化分支深度
  34. if (changeTreeDeep > noChangeTreeDeep) {
  35. root.right = rightRotate(root.right)
  36. }
  37. return leftRotate(root)
  38. }
  39. }
  40. function leftRotate (root) {
  41. // 找到新根
  42. var newRoot = root.right
  43. // 找到变化分支
  44. var changeTree = root.right.left
  45. // 当前旋转节点的右孩子为变化分支
  46. root.right = changeTree
  47. // 新根的左孩子为旋转节点
  48. newRoot.left = root
  49. // 返回新的根节点
  50. return newRoot
  51. }
  52. function rightRotate (root) {
  53. // 找到新根
  54. var newRoot = root.left
  55. // 找到变化分支
  56. var changeTree = root.left.right
  57. // 当前旋转节点的左孩子为变化分支
  58. root.left = changeTree
  59. // 新根的右孩子为旋转节点
  60. newRoot.right = root
  61. // 返回新的根节点
  62. return newRoot
  63. }
  64. function getDeep (root) {
  65. if (root == null) return 0
  66. var leftDeep = getDeep(root.left)
  67. var rightDeep = getDeep(root.right)
  68. return Math.max(leftDeep, rightDeep) + 1//算出左右子树层深后再加当前一层
  69. }
  70. function isBalance (root) {
  71. if (root == null) return true
  72. var leftDeep = getDeep(root.left)
  73. var rightDeep = getDeep(root.right)
  74. if (Math.abs(leftDeep - rightDeep) > 1)//绝对值大于1 则不平衡
  75. {
  76. return false
  77. } else {
  78. return isBalance(root.left) && isBalance(root.right)
  79. }
  80. }
  81. console.log("node2是否为平衡二叉树", isBalance(node8))
  82. var newRoot = change(node8)
  83. console.log("新的二叉树是", newRoot)
  84. console.log("新的二叉树是否为平衡二叉树", isBalance(newRoot))

这个时候其实二叉树还是不平衡

2.左左 右右

如果变化分支的高度比旋转节点的另一侧高度差距超过2 那么单旋之后依旧不平衡

  1. function change (root) {
  2. // 返回平衡之后的根节点
  3. if (isBalance(root)) return root
  4. if (root.left != null) root.left = change(root.left)
  5. if (root.right != null) root.right = change(root.right)
  6. var leftDeep = getDeep(root.left)
  7. var rightDeep = getDeep(root.right)
  8. if (Math.abs(leftDeep - rightDeep) < 2) {
  9. return root
  10. } else if (leftDeep > rightDeep) {//不平衡 左边深 右旋
  11. var changeTreeDeep = getDeep(root.left.right) //获取变化分支深度
  12. var noChangeTreeDeep = getDeep(root.left.left)//获取不变化分支深度
  13. if (changeTreeDeep > noChangeTreeDeep) {
  14. root.left = leftRotate(root.left)
  15. }
  16. var newRoot = rightRotate(root)
  17. newRoot.right = change(root.right)
  18. newRoot = change(newRoot)//右侧分支对自己再做一次平衡
  19. return newRoot
  20. } else if (leftDeep < rightDeep) {//不平衡 右边深 左旋
  21. var changeTreeDeep = getDeep(root.right.left) //获取变化分支深度
  22. var noChangeTreeDeep = getDeep(root.right.right)//获取不变化分支深度
  23. if (changeTreeDeep > noChangeTreeDeep) {
  24. root.right = rightRotate(root.right)
  25. }
  26. var newRoot = leftRotate(root)
  27. newRoot.left = change(newRoot.left)
  28. newRoot = change(newRoot)
  29. return newRoot
  30. }
  31. return root
  32. }

现在变成二叉平衡排序树

3.思考:

  • 二叉平衡排序树性能是极致吗?不是
  • 如果我们要提升二叉平衡排序树的性能该如何做?
  • 影响二叉平衡排序树的性能的点在哪?

答:在于二叉平衡排序树只能有两个叉,导致在节点铺满的时候也会有很多层。
希望可以一个节点存多个数。可以提升空间的性能。

  • 如何才能让查找的效率尽可能的少?

答:树的层级越少,查找效率越高。

  • 怎么样才能让二叉平衡排序树的层数变的更少?

答:如果不是二叉,层数会更少。

叉越多,层数越少,但是叉越多,树的结构就越复杂

 234树

希望一棵树,最多有四个叉(度为4)

234树节点永远在最后一层

234树永远是平衡的(每一个路径高度都相同)

达成了一定的效果,分支变多了,层数变少了,节点中存的树变多了,节点变少了

因为分支多,所以复杂度上升

  • 希望对234树进行简化
  • 希望简化为二叉树
  • 依旧保留多叉
  • 依旧单节点存放多个值

红黑树 

也是二叉平衡排序树 只是有的节点有不同的意义

性质1:节点是红色或黑色。(红色代表啥,黑色代表啥?)

性质2:根节点是黑色。(为啥?黑色节点代表啥?)

性质3:每个红色节点的两个子节点都是黑色。(红色是啥,黑色是啥?)

性质4. 从任一节点到其每个叶子的所有路径都包含相同数目的黑色节点。(为什么不算上红色节点呢)


​​​​​​​

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/爱喝兽奶帝天荒/article/detail/887676
推荐阅读
相关标签
  

闽ICP备14008679号