function quickSort_by_Nico_Lomuto(arr, startIndex, endIndex) {
// using Nico Lomuto partition scheme
// simpler and easier to understand.
if(endIndex > startIndex) {
var partitionIndex = partition_by_Nico_Lomuto(arr, startIndex, endIndex);
// the item at partitionIndex will not be included in recursive sorting because
// arr[partitionIndex] >= [...lowers]
// [...highers] >= arr[partitionIndex]
// recursion to sort lower values
quickSort_by_Nico_Lomuto(arr, startIndex, partitionIndex - 1);
// recursion to sort higher values
quickSort_by_Nico_Lomuto(arr, partitionIndex + 1, endIndex);
}
return arr;
}
function partition_by_Nico_Lomuto(arr, startIndex, endIndex) {
// easier to implement and understand
//var pivot = arr[startIndex];
// Lomuto partitioning has worst case if selected pivot value is LARGEST value in the range!
// prevent worst case by carefully selecting pivot value!
var pivot = selectPivot(arr, startIndex, endIndex, true); // true = MUST do swapping !
var i = startIndex;
// one time loop from bottom to the second from top, because pivot is the top position
for(j = startIndex; endIndex > j; j++) {
// is current element is smaller than or equal to pivot ?
if(pivot >= arr[j]) {
// swap
swap(arr, i, j);
i++;
}
}
// swap
swap(arr, i, endIndex);
return i;
}
function selectPivot(arr, startIndex, endIndex, doSwap) {
// find a pivot value which not the lowest value within the range
// Get 2 UNIQUE elements, if failed then it means all elements are same value.
var pivot = arr[startIndex]; // get first element from the first position
// try to find a different element value
var j = endIndex;
while(pivot == arr[j] && j >= startIndex) {
j--;
}
if(startIndex > j) {
//console.log('selectPivot(arr, ' + startIndex + ',' + endIndex + '), all elements are equal, nothing to sort');
return pivot;
}
// check which element is lower?
// use the lower value as pivot and swap the position with the last position (endIndex)
if(pivot > arr[j]) {
pivot = arr[j];
if(doSwap) {
swap(arr, j, endIndex);
}
} else {
if(doSwap) {
swap(arr, startIndex, endIndex);
}
}
return pivot;
}
function swap(arr, a, b) {
// replace more than 1 element value in array using 1 line
// this ability is 'ES6 destructuring swap',
// only specific for Javascript language
// but VERY VERY SLOW, almost 3 times slower !
//[arr[a], arr[b]] = [arr[b], arr[a]];
// normal way for many programming language
var _swap_temp = arr[a];
arr[a] = arr[b];
arr[b] = _swap_temp;
}