First, the recursive version of Quick sort algorithm:
<script>
function partition(arr, low, high){
var pivot = arr[low];
while (low < high){
while (low < high) {
if (arr[high] <= pivot ){
arr[low] = [arr[high], arr[high]=arr[low]][0];
break;
}
--high;
}
while (low < high){
if (arr[low] > pivot ){
arr[high] = [arr[low], arr[low] = arr[high]][0];
break;
}
++low;
}
}
return low;
}
function Qsort_recursive(arr, low, high){
if ( low < high ){
var loc = partition(arr, low, high);
Qsort_recursive(arr, low, loc-1);
Qsort_recursive(arr, loc+1, high);
}
}
function QuickSort(arr){
Qsort_recursive(arr, 0, arr.length-1);
return arr;
}
console.log(QuickSort([45, 79, 30, 2, 98, 10, 3, 2, 3, 18]));
</script>
Turn the recursive Quick Sort into non-recursive form is basically matter of traversing the binary-tree in preorder, so my version of non-recursive form of Quick Sort algorithm is as such:
function Qsort_nonrecursive(arr, low, high){
var stack = [],
loc,
cur = { low: low, high: high, flag: 0, loc: undefined };
stack.push(cur);
while (stack.length != 0) {
cur = stack.pop();
if (cur.flag == 0 && cur.low < cur.high){
cur.loc = loc = partition(arr, cur.low, cur.high);
cur.flag = 1;
}
if (cur.flag == 1) {
if (cur.low < loc - 1){
stack.push(cur);
stack.push({ low: cur.low, high: cur.loc -1, flag: 0, loc: undefined});
continue;
} else { //cur.low >= loc-1, no more leftbrach push operation;
if (cur.high > loc+1){
stack.push(cur);
stack.push({low: cur.loc+1, high: cur.high, flag: 0, loc: undefined});
} else { //when cur.high <= loc+1, no more right branch push operation; no need to push cur node again
if (stack.length != 0 ) {
stack[stack.length-1].flag == 2 &&
(stack[stack.length -1].flag = 3) ||
(stack[stack.length -1].flag = 2 );
}
}
continue;
}
}
if (cur.flag == 2){ //flag 2, left branch handled;
if ( cur.loc+1 < cur.high) {
stack.push(cur);
stack.push({ low: cur.loc+1, high: cur.high, flag: 0, loc: undefined });
} else {
if (stack.length != 0){
stack[stack.length -1].flag = 3;
}
}
}
if (cur.flag == 3) { //flag 3, return from right branch;
if (stack.length != 0){
stack[stack.length -1].flag == 1 &&
(stack[stack.length -1].flag = 2) ||
(stack[stack.length -1].flag = 3)
}
}
} //end of while
}
function QuickSort_nonrecursive(arr){
var low = 0, high = arr.length-1;
Qsort_nonrecursive(arr, low, high);
return arr;
}
console.log(QuickSort_nonrecursive([45, 79, 30, 2, 98, 10, 3, 2, 3, 18]))
output:
<script>
function partition_reversed(arr, low, high){
var pivot = arr[low];
while (low < high ){
while ( low < high ){
if (arr[high] >= pivot ){
arr[low] = [arr[high], arr[high] = arr[low] ][0];
break;
}
--high;
}
while ( low < high ) {
if (arr[low] < pivot ){
arr[high] = [arr[low], arr[low] = arr[high]][0];
break;
}
++low;
}
}
return low;
}
var K, result;
function findK_QS_recursive(arr,low, high){
if (low == high){
return result = arr[low];
}
if (low < high){
var loc = partition_reversed(arr, low, high);
if (loc == K)
return result = arr[loc];
if (loc < K){
arguments.callee(arr, loc+1, high);
} else {
arguments.callee(arr, low, loc-1);
}
}
}
function findK_QS_base1(arr, N){
if (N > arr.length)
throw "N should NOT exceed arr's length";
K = N - 1;
findK_QS_recursive(arr, 0, arr.length-1);
console.log("recursive: the ", N,"th bigest is ", result, "in ", arr);
}
var c = [27,30, 12, 16, 10, 7, 49, 79];
var d = [56, 32, 12, 1, 10, 5, 19, 8, 3, 90, 100, 48, 67];
findK_QS_base1(c, 4);
findK_QS_base1(d, 6);
function findK_QS_nonrecursive(arr, N){
var stack = [],
ret,
M = N -1,
low = 0, high = arr.length -1;
stack.push({ low: low, high: high, loc: undefined, flag: 0});
while (stack.length != 0){
var cur, loc;
cur = stack.pop();
if ( cur.flag == 0){
cur.loc = loc = partition_reversed(arr, cur.low, cur.high);
cur.flag = 1; //1: currrent node calculated;
if (loc == M)
return ret = arr[loc];
}
if (cur.flag == 1){
if ( loc < M){
if ( cur.loc+1 < cur.high){
stack.push(cur);
stack.push({ low: cur.loc+1, high: cur.high, loc: undefined, flag: 0 });
} else {
if (cur.loc+1 == cur.high){
return ret = arr[cur.high];
}
console.log("Error1", cur);
throw new Error("Error1");
}
} else if ( loc > M) {
if (cur.low < cur.loc-1){
stack.push(cur);
stack.push({ low: cur.low, high: cur.loc -1, flag: 0, loc: undefined});
} else {
if (cur.low == cur.loc-1){
return ret = arr[cur.low];
}
console.log("Error2", cur);
throw new Error("Error2");
}
}
}
}
}
var Z = 4, Y = 6;
var G = findK_QS_nonrecursive(c, Z);
console.log("nonrecursive: the ", Z, "th bigest is ", G, "in ", c);
var H = findK_QS_nonrecursive(d, Y);
console.log("nonrecursive: the ", Y, "th bigest is ", H, "in ", d);
</script>
the output is :