这个仓库很早之前就想做了,最近正好有面试,就整理一下,把原来学习的Java相关的数据结构与算法仓库里的内容移植到JavaScript中。

二分查找

  1. const {
  2. ArrayGenerator
  3. } = require('./util')
  4. const {
  5. LinerSearch
  6. } = require('./线性查找')
  7. class BinarySearch {
  8. constructor() {
  9. }
  10. /**
  11. * 二分搜索前提就是数组是有序的单调的
  12. *
  13. * @param data
  14. * @param target
  15. * @param <E>
  16. * @return
  17. */
  18. static searchRWrapper(data, target) {
  19. return BinarySearch.searchR(data, 0, data.length - 1, target);
  20. }
  21. static searchR(data, l, r, target) {
  22. if (l > r) {
  23. return -1;
  24. }
  25. let mid = Math.floor(l + (r - l) / 2);
  26. if (target === data[mid]) {
  27. return mid;
  28. } else if (target > data[mid]) {
  29. // target > data[mid]
  30. return BinarySearch.searchR(data, mid + 1, r, target);
  31. } else { // target < data[mid]
  32. return BinarySearch.searchR(data, l, mid - 1, target);
  33. }
  34. }
  35. static main() {
  36. // 使用二分搜索,必须保证待查找集合是单调的
  37. const STATUS = {
  38. order: '有序单调',
  39. random: '随机无需'
  40. }
  41. const status = STATUS.random
  42. let count = 100000;
  43. let arr = []
  44. if (status === STATUS.order) {
  45. // 有序单调数组
  46. arr = ArrayGenerator.generateOrderArray(count);
  47. } else {
  48. // 无序数组,极有可能查询不到待查元素
  49. arr = ArrayGenerator.generateRandomArray(count, count);
  50. }
  51. // let arr = [-1, 0, 3, 5, 9, 12];
  52. const target = Math.floor(Math.random() * count)
  53. let startTime = new Date().valueOf()
  54. let result = -1
  55. for (let i = 0; i < 10000; i++) {
  56. result = BinarySearch.searchRWrapper(arr, target);
  57. }
  58. console.log(`result ${result}`)
  59. let endTime = new Date().valueOf()
  60. console.log(`BinarySearch time is ${endTime - startTime}ms`)
  61. startTime = new Date().valueOf()
  62. for (let i = 0; i < 10000; i++) {
  63. result = LinerSearch.search(arr, target)
  64. }
  65. console.log(`result ${result}`)
  66. endTime = new Date().valueOf()
  67. console.log(`LinerSearch time is ${endTime - startTime}ms`)
  68. }
  69. }
  70. BinarySearch.main()

二叉树

  1. const {
  2. arr2tree
  3. } = require('./util')
  4. class BinaryTree {
  5. // 非递归前序遍历
  6. // 深度优先遍历
  7. /** 深度优先遍历 */
  8. static preOrderNR(root) {
  9. let stack = [];
  10. stack.push(root);
  11. while (stack.length) {
  12. let top = stack.pop();
  13. console.log(top);
  14. if (top.right != null) {
  15. stack.push(top.right);
  16. }
  17. if (top.left != null) {
  18. stack.push(top.left);
  19. }
  20. }
  21. }
  22. /** 前序遍历 */
  23. static preOrder(node) {
  24. if (node == null) {
  25. return;
  26. }
  27. // 访问节点
  28. // 前序遍历 开始
  29. console.log(node);
  30. BinaryTree.preOrder(node.left);
  31. BinaryTree.preOrder(node.right);
  32. // 前序遍历 结束
  33. }
  34. /** 中序遍历 */
  35. static inOrder(node) {
  36. if (node == null) {
  37. return;
  38. }
  39. // 访问节点
  40. // 中序遍历 开始
  41. BinaryTree.inOrder(node.left);
  42. console.log(node);
  43. BinaryTree.inOrder(node.right);
  44. // 中序遍历 结束
  45. }
  46. // 层序遍历
  47. // 广度优先遍历
  48. // 如果做图的遍历,要做记录,查看当前节点是否遍历过,否则会产生重复(一个节点的父亲节点可能有多个)
  49. // 树结构不存在这个情况
  50. /** 层序遍历 */
  51. static levelOrder(root) {
  52. let queue = [];
  53. queue.push(root);
  54. while (queue.length) {
  55. let cur = queue.shift();
  56. console.log(cur);
  57. if (cur.left != null) {
  58. queue.push(cur.left);
  59. }
  60. if (cur.right != null) {
  61. queue.push(cur.right);
  62. }
  63. }
  64. }
  65. /** 层序遍历,并将每层元素放到对用数组中 */
  66. static inorderTraversal(root) {
  67. let res = [];
  68. let queue = [root];
  69. while (queue.length) {
  70. let cur = [];
  71. // 当前层
  72. let index = queue.length;
  73. // 遍历当前层得到下一层
  74. for (let i = 0; i < index; i++) {
  75. let qu = queue.shift();
  76. cur.push(qu);
  77. if (qu.left) {
  78. queue.push(qu.left);
  79. }
  80. if (qu.right) {
  81. queue.push(qu.right);
  82. }
  83. }
  84. res.push(cur);
  85. }
  86. console.log(res)
  87. return res
  88. }
  89. static main(root) {
  90. // BinaryTree.preOrderNR(root)
  91. // BinaryTree.preOrder(root)
  92. // BinaryTree.inOrder(root)
  93. // BinaryTree.levelOrder(root)
  94. BinaryTree.inorderTraversal(root)
  95. }
  96. }
  97. const tree = arr2tree([1, 2, 3, 4, 5, 6, 7])
  98. BinaryTree.main(tree)
  99. /*
  100. 1
  101. 2 3
  102. 4 5 6 7
  103. */
  104. // 4 2 5 1 6 3 7 中序遍历
  105. // 1 2 4 5 3 6 7 前序遍历
  106. // 4 5 2 6 7 3 1 后序遍历

常用快排

  1. function sort(arr) {
  2. quickSort(arr, 0, arr.length - 1)
  3. }
  4. function quickSort(arr, l, r) {
  5. if (l > r) return;
  6. let p = partition(arr, l, r);
  7. quickSort(arr, l, p - 1);
  8. quickSort(arr, p + 1, r);
  9. }
  10. function partition(arr, l, r) {
  11. // [l/i,j.....r]
  12. // [l - i] < v
  13. // [i - j - 1] > v
  14. let i = l;
  15. let j = i + 1;
  16. let v = arr[l];
  17. while (j <= r) {
  18. // 小交换,大向前走
  19. if (arr[j] < v) { // 看索引j位置的成员是否小于v
  20. i++;
  21. [arr[i], arr[j]] = [arr[j], arr[i]];
  22. }
  23. j++;
  24. }
  25. [arr[l], arr[i]] = [arr[i], arr[l]];
  26. return i;
  27. }
  28. let arr = [4, 6, 8, 2, 3, 1, 0];
  29. sort(arr);
  30. console.log(arr);