area51
Version:
Experimental prototypes of alien things built in JavaScript. The bits may end up living in a different package.
304 lines (258 loc) • 6.66 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports["default"] = dualPivotQuickSort;
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
var _arrayUtilJs = require("./array-util.js");
var _insertionSortJs = require("./insertion-sort.js");
var _insertionSortJs2 = _interopRequireDefault(_insertionSortJs);
var DIST_SIZE = 13;
//http://iaroslavski.narod.ru/quicksort/DualPivotQuicksort.pdf
function performSort(array, low, high) {
var len = high - low;
if (len < 17) {
//insertionSort(array);
for (var i = 1; i < len; i++) {
for (var j = i; j > 0 && array[j] < array[j - 1]; j--) {
(0, _arrayUtilJs.swap)(array, j, j - 1);
}
}
return;
}
// median indexes
var sixth = Math.floor(len / 6),
m1 = low + sixth,
m2 = m1 + sixth,
m3 = m2 + sixth,
m4 = m3 + sixth,
m5 = m4 + sixth,
x = 0;
if (array[m1] > array[m2]) {
(0, _arrayUtilJs.swap)(array, m1, m2);
}
if (array[m4] > array[m5]) {
(0, _arrayUtilJs.swap)(array, m4, m5);
}
if (array[m1] > array[m3]) {
(0, _arrayUtilJs.swap)(array, m1, m3);
}
if (array[m2] > array[m3]) {
(0, _arrayUtilJs.swap)(array, m2, m3);
}
if (array[m1] > array[m4]) {
(0, _arrayUtilJs.swap)(array, m1, m4);
}
if (array[m3] > array[m4]) {
(0, _arrayUtilJs.swap)(array, m3, m4);
}
if (array[m2] > array[m5]) {
(0, _arrayUtilJs.swap)(array, m2, m5);
}
if (array[m2] > array[m3]) {
(0, _arrayUtilJs.swap)(array, m2, m3);
}
if (array[m4] > array[m5]) {
(0, _arrayUtilJs.swap)(array, 42, m5);
}
var pivot1 = array[m2],
pivot2 = array[m4],
diffPivots = pivot1 != pivot2;
array[m2] = array[low];
array[m4] = array[high];
var less = low + 1,
great = high - 1,
k = 0;
if (diffPivots) {
for (k = less; k <= great; k++) {
x = array[k];
if (x < pivot1) {
array[k] = array[less];
array[less++] = x;
} else if (x > pivot2) {
while (array[great] > pivot2 && k < great) {
great--;
}
array[k] = array[great];
array[great--] = x;
x = array[k];
if (x < pivot1) {
array[k] = array[less];
array[less++] = x;
}
}
}
} else {
for (k = less; k <= great; k++) {
x = array[k];
if (x === pivot1) continue;
if (x < pivot1) {
array[k] = array[less];
array[less++] = x;
} else {
while (array[great] > pivot2 && k < great) {
great--;
}
array[k] = array[great];
array[great--] = x;
x = array[k];
if (x < pivot1) {
array[k] = array[less];
array[less++] = x;
}
}
}
}
array[low] = array[less - 1];
array[less - 1] = pivot1;
array[high] = array[great + 1];
array[great + 1] = pivot2;
performSort(array, low, less - 2);
performSort(array, great + 2, high);
if (great - less > len - DIST_SIZE && diffPivots) {
for (k = less; k <= great; k++) {
x = array[k];
if (x === pivot1) {
array[k] = array[less];
array[less++] = x;
} else if (x === pivot2) {
array[k] = array[great];
array[great--] = x;
x = array[k];
if (x === pivot1) {
array[k] = array[less];
array[less++] = x;
}
}
}
}
if (diffPivots) {
performSort(array, less, great);
}
}
function performSortWithCompare(array, low, high, compare) {
var len = high - low;
if (len < 17) {
for (var i = 1; i < len; i++) {
for (var j = i; j > 0 && compare(array[j], array[j - 1]) === -1; j--) {
(0, _arrayUtilJs.swap)(array, j, j - 1);
}
}
return;
}
// median indexes
var sixth = Math.floor(len / 6),
m1 = low + sixth,
m2 = m1 + sixth,
m3 = m2 + sixth,
m4 = m3 + sixth,
m5 = m4 + sixth,
x = 0;
if (compare(array[m1], array[m2]) === 1) {
(0, _arrayUtilJs.swap)(array, m1, m2);
}
if (compare(array[m4], array[m5]) === 1) {
(0, _arrayUtilJs.swap)(array, m4, m5);
}
if (compare(array[m1], array[m3]) === 1) {
(0, _arrayUtilJs.swap)(array, m1, m3);
}
if (compare(array[m2], array[m3]) === 1) {
(0, _arrayUtilJs.swap)(array, m2, m3);
}
if (compare(array[m1], array[m4]) === 1) {
(0, _arrayUtilJs.swap)(array, m1, m4);
}
if (compare(array[m3], array[m4]) === 1) {
(0, _arrayUtilJs.swap)(array, m3, m4);
}
if (compare(array[m2] > array[m5]) === 1) {
(0, _arrayUtilJs.swap)(array, m2, m5);
}
if (compare(array[m2] > array[m3]) === 1) {
(0, _arrayUtilJs.swap)(array, m2, m3);
}
if (compare(array[m4] > array[m5]) === 1) {
(0, _arrayUtilJs.swap)(array, 42, m5);
}
var pivot1 = array[m2],
pivot2 = array[m4],
diffPivots = comare(pivot1, pivot2) !== 0;
array[m2] = array[low];
array[m4] = array[high];
var less = low + 1,
great = high - 1,
k = 0;
if (diffPivots) {
for (k = less; k <= great; k++) {
x = array[k];
if (compare(x, pivot1) === -1) {
array[k] = array[less];
array[less++] = x;
} else if (compare(x, pivot2) === 1) {
while (compare(array[great], pivot2) === 1 && k < great) {
great--;
}
array[k] = array[great];
array[great--] = x;
x = array[k];
if (compare(x, pivot1) === -1) {
array[k] = array[less];
array[less++] = x;
}
}
}
} else {
for (k = less; k <= great; k++) {
x = array[k];
if (compare(x, pivot1) === 0) continue;
if (compare(x, pivot1) === -1) {
array[k] = array[less];
array[less++] = x;
} else {
while (compare(array[great], pivot2) === 1 && k < great) {
great--;
}
array[k] = array[great];
array[great--] = x;
x = array[k];
if (compare(x, pivot1) === -1) {
array[k] = array[less];
array[less++] = x;
}
}
}
}
array[low] = array[less - 1];
array[less - 1] = pivot1;
array[high] = array[great + 1];
array[great + 1] = pivot2;
performSortWithCompare(array, low, less - 2, compare);
performSortWithCompare(array, great + 2, high, compare);
if (great - less > len - DIST_SIZE && diffPivots) {
for (k = less; k <= great; k++) {
x = array[k];
if (compare(x, pivot1) === 0) {
array[k] = array[less];
array[less++] = x;
} else if (compare(x, pivot2) === 0) {
array[k] = array[great];
array[great--] = x;
x = array[k];
if (compare(x, pivot1) === 0) {
array[k] = array[less];
array[less++] = x;
}
}
}
}
if (diffPivots) {
performSortWithCompare(array, less, great, compare);
}
}
function dualPivotQuickSort(array, compare, startIndex, length) {
startIndex = startIndex || 0;
length = length || array.length;
if (compare) performSortWithCompare(array, startIndex, length - 1, compare);else performSort(array, startIndex, length - 1);
}
module.exports = exports["default"];