RosettaCodeData/Task/Quickselect-algorithm/JavaScript/quickselect-algorithm-1.js

72 lines
1.9 KiB
JavaScript

// this just helps make partition read better
function swap(items, firstIndex, secondIndex) {
var temp = items[firstIndex];
items[firstIndex] = items[secondIndex];
items[secondIndex] = temp;
};
// many algorithms on this page violate
// the constraint that partition operates in place
function partition(array, from, to) {
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/random
var pivotIndex = getRandomInt(from, to),
pivot = array[pivotIndex];
swap(array, pivotIndex, to);
pivotIndex = from;
for(var i = from; i <= to; i++) {
if(array[i] < pivot) {
swap(array, pivotIndex, i);
pivotIndex++;
}
};
swap(array, pivotIndex, to);
return pivotIndex;
};
// later versions of JS have TCO so this is safe
function quickselectRecursive(array, from, to, statistic) {
if(array.length === 0 || statistic > array.length - 1) {
return undefined;
};
var pivotIndex = partition(array, from, to);
if(pivotIndex === statistic) {
return array[pivotIndex];
} else if(pivotIndex < statistic) {
return quickselectRecursive(array, pivotIndex, to, statistic);
} else if(pivotIndex > statistic) {
return quickselectRecursive(array, from, pivotIndex, statistic);
}
};
function quickselectIterative(array, k) {
if(array.length === 0 || k > array.length - 1) {
return undefined;
};
var from = 0, to = array.length,
pivotIndex = partition(array, from, to);
while(pivotIndex !== k) {
pivotIndex = partition(array, from, to);
if(pivotIndex < k) {
from = pivotIndex;
} else if(pivotIndex > k) {
to = pivotIndex;
}
};
return array[pivotIndex];
};
KthElement = {
find: function(array, element) {
var k = element - 1;
return quickselectRecursive(array, 0, array.length, k);
// you can also try out the Iterative version
// return quickselectIterative(array, k);
}
}