树是一种分层数据的抽象模型。由一个或多个父子关系的节点组成。

相关术语

image.png

  • 根节点 :位于树的顶部的节点叫根节点
  • 内部节点 :至少有一个子节点的节点称为内部节点,如上图的 7,5,9,15,13,20
  • 外部节点 :一个节点都没有的节点称为外部节点,也叫 叶节点 ,如上图的 3,6,8,10,12,14,18,25
  • 子树 :由节点和他的后代节点组成,如上图的 13,12,14 构成了一个子树
  • 节点深度 :节点的深度取决于节点的祖先节点的数量,如上图的节点3,它的祖先节点有 5,7,11, 所以它的节点深度为3
  • 树的高度 :树的高度是所有节点的深度的最大值,如上图树的高度最大的节点深度为3,其树的高度也就是3。也可以通过分层,根节点在第0层,子节点在第1层,依此类推,可得到树的高度。

二叉树

二叉树就是只有两个节点的树,一个左节点和一个右节点。

二叉搜索树

二叉搜索树(BST),是二叉树的一种,他的特点是左侧节点比父节点小,右侧节点比父节点大。

  1. class Node {
  2. constructor(key) {
  3. this.key = key;
  4. this.left = null;
  5. this.right = null;
  6. }
  7. }
  8. class BinarySearchTree {
  9. constructor() {
  10. this.root = null;
  11. }
  12. insert(key) {
  13. if (this.root) {
  14. this.insertNode(this.root, key);
  15. } else {
  16. this.root = new Node(key);
  17. }
  18. }
  19. insertNode(node, key) {
  20. if (key < node.key) {
  21. if (node.left) {
  22. this.insertNode(node.left, key);
  23. } else {
  24. node.left = new Node(key);
  25. }
  26. } else {
  27. if (node.right) {
  28. this.insertNode(node.right, key);
  29. } else {
  30. node.right = new Node(key);
  31. }
  32. }
  33. }
  34. /**
  35. * 中序遍历
  36. * 从小到大访问节点
  37. * @param {*} callback
  38. */
  39. inOrderTraverse(callback) {
  40. this.inOrderTraverseNode(this.root, callback);
  41. }
  42. inOrderTraverseNode(node, callback) {
  43. if (node) {
  44. this.inOrderTraverseNode(node.left, callback);
  45. callback(node.key);
  46. this.inOrderTraverseNode(node.right, callback);
  47. }
  48. }
  49. /**
  50. * 先序遍历
  51. * 从上往下,先左后右访问节点
  52. * @param {*} callback
  53. */
  54. preOrderTraverse(callback) {
  55. this.preOrderTraverseNode(this.root, callback);
  56. }
  57. preOrderTraverseNode(node, callback) {
  58. if (node) {
  59. callback(node.key);
  60. node.left && this.preOrderTraverseNode(node.left, callback);
  61. node.right && this.preOrderTraverseNode(node.right, callback);
  62. }
  63. }
  64. /**
  65. * 后序遍历
  66. * 从下往下,先左后右访问节点
  67. * @param {*} callback
  68. */
  69. postOrderTraverse(callback) {
  70. this.postOrderTraverseNode(this.root, callback);
  71. }
  72. postOrderTraverseNode(node, callback) {
  73. if (node) {
  74. node.left && this.postOrderTraverseNode(node.left, callback);
  75. node.right && this.postOrderTraverseNode(node.right, callback);
  76. callback(node.key);
  77. }
  78. }
  79. min() {
  80. return this.minNode(this.root);
  81. }
  82. minNode(node) {
  83. let current = node;
  84. while (current && current.left) {
  85. current = current.left;
  86. }
  87. return current;
  88. }
  89. max() {
  90. let current = this.root;
  91. while (current && current.right) {
  92. current = current.right;
  93. }
  94. return current;
  95. }
  96. search(key) {
  97. return this.searchNode(this.root, key);
  98. }
  99. searchNode(node, key) {
  100. if (!node) return false;
  101. if (key < node.key) {
  102. return this.searchNode(node.left, key);
  103. } else if (key > node.key) {
  104. return this.searchNode(node.right, key);
  105. } else {
  106. return true;
  107. }
  108. }
  109. remove(key) {
  110. return this.removeNode(this.root, key);
  111. }
  112. removeNode(node, key) {
  113. if (!node) return null;
  114. if (key < node.key) {
  115. node.left = this.removeNode(node.left, key);
  116. return node;
  117. } else if (key > node.key) {
  118. node.right = this.removeNode(node.right, key);
  119. } else {
  120. if (!node.left && !node.right) {
  121. node = null;
  122. } else if (node.left && !node.right) {
  123. node = node.left;
  124. } else if (!node.left && node.right) {
  125. node = node.right;
  126. } else {
  127. let minNode = this.minNode(node.right);
  128. node.key = minNode.key;
  129. node.right = this.removeNode(node.right, minNode.key);
  130. }
  131. return node;
  132. }
  133. }
  134. toString() {
  135. return JSON.stringify(this.root, null, 2);
  136. }
  137. }
  138. const tree = new BinarySearchTree();
  139. tree.insert(11);
  140. tree.insert(7);
  141. tree.insert(15);
  142. tree.insert(5);
  143. tree.insert(3);
  144. tree.insert(9);
  145. tree.insert(8);
  146. tree.insert(10);
  147. tree.insert(13);
  148. tree.insert(12);
  149. tree.insert(14);
  150. tree.insert(20);
  151. tree.insert(18);
  152. tree.insert(25);
  153. tree.insert(6);
  154. tree.remove(5)
  155. console.log(tree.toString());

AVL 自平衡树

红黑树