08354e42bbfbc3e762da0112601ec61a8731a70c734a24ea64418a3fb81f8dfe6dd550a8580cd5c57581fa96e7e7e82f80a35a942f59a2b8506569ae844922 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. import LinkedList from '../dataStructures/linkedList';
  2. /**
  3. * Refactored implementation of mergeSort (part of javascript-algorithms project) by Github users:
  4. * mgechev, AndriiHeonia and lekkas (part of javascript-algorithms project - all project contributors
  5. * at repository website)
  6. *
  7. * Link to repository: https://github.com/mgechev/javascript-algorithms
  8. */
  9. /**
  10. * Specifies a function that defines the sort order. The array is sorted according to each
  11. * character's Unicode code point value, according to the string conversion of each element.
  12. *
  13. * @param a {*} first compared element.
  14. * @param b {*} second compared element.
  15. * @returns {Number}
  16. */
  17. var defaultCompareFunction = function defaultCompareFunction(a, b) {
  18. // sort lexically
  19. var firstValue = a.toString();
  20. var secondValue = b.toString();
  21. if (firstValue === secondValue) {
  22. return 0;
  23. } else if (firstValue < secondValue) {
  24. return -1;
  25. }
  26. return 1;
  27. };
  28. /**
  29. * Mergesort method which is recursively called for sorting the input array.
  30. *
  31. * @param {Array} array The array which should be sorted.
  32. * @param {Function} compareFunction Compares two items in an array. If compareFunction is not supplied,
  33. * elements are sorted by converting them to strings and comparing strings in Unicode code point order.
  34. * @param {Number} startIndex Left side of the subarray.
  35. * @param {Number} endIndex Right side of the subarray.
  36. * @returns {Array} Array with sorted subarray.
  37. */
  38. export default function mergeSort(array) {
  39. var compareFunction = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : defaultCompareFunction;
  40. var startIndex = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
  41. var endIndex = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : array.length;
  42. if (Math.abs(endIndex - startIndex) <= 1) {
  43. return [];
  44. }
  45. var middleIndex = Math.ceil((startIndex + endIndex) / 2);
  46. mergeSort(array, compareFunction, startIndex, middleIndex);
  47. mergeSort(array, compareFunction, middleIndex, endIndex);
  48. return merge(array, compareFunction, startIndex, middleIndex, endIndex);
  49. }
  50. /**
  51. * Devides and sort merges two subarrays of given array
  52. *
  53. * @param {Array} array The array which subarrays should be sorted.
  54. * @param {Number} startIndex The start of the first subarray.
  55. * This subarray is with end middle - 1.
  56. * @param {Number} middleIndex The start of the second array.
  57. * @param {Number} endIndex end - 1 is the end of the second array.
  58. * @returns {Array} The array with sorted subarray.
  59. */
  60. export function merge(array, compareFunction, startIndex, middleIndex, endIndex) {
  61. var leftElements = new LinkedList();
  62. var rightElements = new LinkedList();
  63. var leftSize = middleIndex - startIndex;
  64. var rightSize = endIndex - middleIndex;
  65. var maxSize = Math.max(leftSize, rightSize);
  66. var size = endIndex - startIndex;
  67. for (var _i = 0; _i < maxSize; _i += 1) {
  68. if (_i < leftSize) {
  69. leftElements.push(array[startIndex + _i]);
  70. }
  71. if (_i < rightSize) {
  72. rightElements.push(array[middleIndex + _i]);
  73. }
  74. }
  75. var i = 0;
  76. while (i < size) {
  77. if (leftElements.first && rightElements.first) {
  78. if (compareFunction(leftElements.first.data, rightElements.first.data) > 0) {
  79. array[startIndex + i] = rightElements.shift().data;
  80. } else {
  81. array[startIndex + i] = leftElements.shift().data;
  82. }
  83. } else if (leftElements.first) {
  84. array[startIndex + i] = leftElements.shift().data;
  85. } else {
  86. array[startIndex + i] = rightElements.shift().data;
  87. }
  88. i += 1;
  89. }
  90. return array;
  91. };