I’ve (designed and) carried out this fancy sorting algorithm that mixes pure runs within the enter array with a heap information construction:
perform ArrayRangeException(message) {
this.message = message;
this.getMessage = perform() { return this.message; }
}
perform RangeCheck(arrayLength, fromIndex, toIndex) {
if (fromIndex < 0) {
throw new ArrayRangeException("'fromIndex' is detrimental: " + fromIndex);
}
if (toIndex > arrayLength) {
throw new ArrayRangeException(
"'toIndex' is simply too massive: " + toIndex + ", array size: " +
arrayLength);
}
if (fromIndex > toIndex) {
throw new ArrayRangeException(
"fromIndex(" + fromIndex + ") > toIndex(" + toIndex + ")");
}
}
perform RunHeap(array, cmp) {
this.cmp = cmp;
this.array = array;
const auxArrayLength = (array.size >>> 1) + 1;
this.fromIndexArray = Array(auxArrayLength);
this.toIndexArray = Array(auxArrayLength);
this.measurement = 0;
this.pushRun = perform(fromIndex, toIndex) {
const nodeIndex = this.measurement++;
this.fromIndexArray[nodeIndex] = fromIndex;
this.toIndexArray[nodeIndex] = toIndex;
},
this.popElement = perform() {
const returnValue = this.array[this.fromIndexArray[0]];
this.fromIndexArray[0]++;
if (this.fromIndexArray[0] === this.toIndexArray[0]) {
const last1 = this.fromIndexArray[--this.size];
this.fromIndexArray[0] = last1;
const last2 = this.toIndexArray[this.size];
this.toIndexArray[0] = last2;
}
this.siftDown(0);
return returnValue;
},
this.swap = perform(array, index1, index2) {
const tmp = array[index1];
array[index1] = array[index2];
array[index2] = tmp;
},
this.isLessThan = perform(runIndex1, runIndex2) {
const element1 = this.array[this.fromIndexArray[runIndex1]];
const element2 = this.array[this.fromIndexArray[runIndex2]];
const cmp = this.cmp(element1, element2);
if (cmp != 0) {
return cmp < 0;
}
return this.fromIndexArray[runIndex1] < this.fromIndexArray[runIndex2];
},
this.siftDown = perform(index) {
let nodeIndex = index;
let leftChildIndex = (index << 1) + 1
let rightChildIndex = leftChildIndex + 1;
let minIndex = index;
whereas (true) {
if (leftChildIndex < this.measurement
&& this.isLessThan(leftChildIndex, nodeIndex)) {
minIndex = leftChildIndex;
}
if (rightChildIndex < this.measurement
&& this.isLessThan(rightChildIndex, minIndex)) {
minIndex = rightChildIndex;
}
if (minIndex === nodeIndex) {
return;
}
this.swap(this.fromIndexArray, minIndex, nodeIndex);
this.swap(this.toIndexArray, minIndex, nodeIndex);
nodeIndex = minIndex;
leftChildIndex = (nodeIndex << 1) + 1;
rightChildIndex = leftChildIndex + 1;
}
},
this.buildHeap = perform() {
for (i = Math.flooring(this.measurement / 2); i >= 0; --i) {
this.siftDown(i);
}
},
this.extendRun = perform(size) {
this.toIndexArray[this.size - 1] += size;
},
this.appendRun = perform(fromIndex, toIndex) {
this.fromIndexArray[this.size] = fromIndex;
this.toIndexArray[this.size] = toIndex;
this.measurement++;
}
}
perform reverseRun(array, fromIndex, toIndex) {
for (i1 = fromIndex, i2 = toIndex; i1 < i2; i1++, i2--) {
const savedArrayComponent = array[i1];
array[i1] = array[i2];
array[i2] = savedArrayComponent;
}
}
perform createRunHeap(array, cmp) {
let runHeap = new RunHeap(array, cmp);
let left = 0;
let proper = 1;
let final = array.size - 1;
let previousWasDescending = false;
whereas (left < final) {
head = left;
proper = left + 1;
if (cmp(array[left], array[right]) <= 0) {
whereas (left < final && cmp(array[left], array[right]) <= 0) {
++left;
++proper;
}
if (previousWasDescending) {
if (cmp(array[head - 1], array[head]) <= 0) {
runHeap.extendRun(proper - head);
} else {
runHeap.appendRun(head, proper);
}
} else {
runHeap.appendRun(head, proper);
}
previousWasDescending = false;
} else { // Scan a descending run:
whereas (left < final && cmp(array[left], array[right]) > 0) {
++left;
++proper;
}
reverseRun(array, head, left);
if (previousWasDescending) {
if (cmp(array[head - 1], array[head]) <= 0) {
runHeap.extendRun(proper - head);
} else {
runHeap.appendRun(head, proper);
}
} else {
runHeap.appendRun(head, proper);
}
previousWasDescending = true;
}
++left;
++proper;
}
if (left === final) {
if (cmp(array[last - 1], array[last]) <= 0) {
runHeap.extendRun(1);
} else {
runHeap.appendRun(final, final + 1);
}
}
return runHeap;
}
Array.prototype.heapSelectionSort =
perform(cmp, fromIndex, toIndex) {
if (!cmp) {
cmp = (a, b) => a - b;
}
if (!fromIndex) {
fromIndex = 0;
}
if (!toIndex) {
toIndex = this.size;
}
RangeCheck(this.size, fromIndex, toIndex);
if (toIndex - fromIndex < 2) {
return this;
}
const aux = this.slice(fromIndex, toIndex);
const runHeap = createRunHeap(aux, cmp);
runHeap.buildHeap();
let index = fromIndex;
whereas (index < toIndex) {
this[index] = runHeap.popElement();
index++;
}
return this;
};
(All the demo gist is right here: https://gist.github.com/coderodde/47ae57983954c89ab7bef21b3fa7b232)
Critique request
Since I’m not knowledgeable Javascript developer, I want to make my code above on par with idiomatic JS code.