HTML Preparation code:
x
 
1
<script>
2
  
3
function sortArray(arr) {
4
  let passDownArr = [];
5
  const { max, min } = findMaxMin(arr);
6
  passDownArr = cutArr(arr, max, min);
7
  if (arr.length <= 2 || isSorted(arr)) {
8
    if (arr[0] > arr[1]) {
9
      return [arr[1], arr[0]];
10
    } else {
11
      return arr;
12
    }
13
  } else {
14
    let sorted = sortArray(passDownArr);
15
    let tempArr1 = concatArray(sorted, [max]);
16
    let tempArr2 = concatArray([min], tempArr1);
17
    return tempArr2;
18
  }
19
}
20
function findMaxMin(arr) {
21
  let max = arr[0];
22
  let min = arr[0];
23
  for (let i = 1; i < arr.length; i++) {
24
    if (arr[i] > max) {
25
      max = arr[i];
26
    }
27
    if (arr[i] < min) {
28
      min = arr[i];
29
    }
30
  }
31
  return { max: max, min: min };
32
}
33
function isSorted(arr) {
34
  let min = arr[0];
35
  for (let i = 1; i < arr.length; i++) {
36
    if (arr[i] < min) {
37
      return false;
38
    }
39
  }
40
  return true;
41
}
42
function cutArr(arr, max, min) {
43
  arr = removeFromArr(max, arr);
44
  arr = removeFromArr(min, arr);
45
  return arr;
46
}
47
48
function removeFromArr(el, arr) {
49
  let temp1 = [],
50
    temp2 = [],
51
    retArr = [];
52
  let index = arr.indexOf(el);
53
  temp1 = arr.slice(0, index);
54
  temp2 = arr.slice(index + 1, arr.length);
55
  retArr = concatArray(temp1, temp2);
56
  return retArr;
57
}
58
59
function concatArray(arr1, arr2) {
60
  let retArr = [];
61
  arr1.forEach((el) => retArr.push(el));
62
  arr2.forEach((el) => retArr.push(el));
63
  return retArr;
64
}
65
66
  
67
  
68
  
69
  function swap(ary, a, b) {
70
      var t = ary[a];
71
      ary[a] = ary[b];
72
      ary[b] = t;
73
  }
74
  
75
  // Built-in with comparison function (default sorting is "dictionary-style")
76
  function builtin_sort(ary) {
77
      return ary.sort(function(a, b) {
78
          return a - b;
79
      });
80
  }
81
  
82
  // Bubble Sort
83
  function bubble_sort(ary) {
84
      var a, b;
85
      for (a = 0; a < ary.length; a++) {
86
          for (b = a + 1; b < ary.length; b++) {
87
              if (ary[a] > ary[b]) {
88
                  swap(ary, a, b);
89
              }
90
          }
91
      }
92
  
93
      return ary;
94
  }
95
  //Insertion sort
96
  function insertion_sort(ary) {
97
        for(var i=1,l=ary.length;i<l;i++) {
98
            var value = ary[i];
99
            for(var j=i - 1;j>=0;j--) {
100
                if(ary[j] <= value)
101
                    break;
102
                ary[j+1] = ary[j];
103
            }
104
            ary[j+1] = value;
105
        }
106
        return ary;
107
  }
108
  
109
  // Naive (but understandable) quicksort (memory hog)
110
  function naive_quicksort(ary) {
111
      if (ary.length <= 1) {
112
          return ary;
113
      }
114
  
115
      var less = [],
116
          greater = [],
117
          pivot = ary.pop();
118
  
119
      for (var i = 0; i < ary.length; i++) {
120
          if (ary[i] < pivot) {
121
              less.push(ary[i]);
122
          } else {
123
              greater.push(ary[i]);
124
          }
125
      }
126
  
127
      less = naive_quicksort(less);
128
      greater = naive_quicksort(greater);
129
  
130
      return less.concat(pivot, greater);
131
  }
132
  
133
  // In place quicksort
134
  function inplace_quicksort_partition(ary, start, end, pivotIndex) {
135
      var i = start, j = end;
136
      var pivot = ary[pivotIndex];
137
      
138
      while(true) {
139
          while(ary[i] < pivot) {i++};
140
          j--;
141
          while(pivot < ary[j]) {j--};
142
          if(!(i<j)) {
143
              return i;
144
          }
145
          swap(ary,i,j);
146
          i++;
147
     }
148
  }
149
  
150
  function inplace_quicksort(ary, start, end) {
151
      if (start < end - 1) {
152
          var pivotIndex = Math.round((start + end) / 2);
153
  
154
          pivotIndex = inplace_quicksort_partition(ary, start, end, pivotIndex);
155
  
156
          inplace_quicksort(ary, start, pivotIndex - 1);
157
          inplace_quicksort(ary, pivotIndex + 1, end);
158
      }
159
  
160
      return ary;
161
  }
162
  
163
  // Heap sort
164
  function heapSort(ary) {
165
      heapify(ary);
166
  
167
      for (var end = ary.length - 1; end > 0; end--) {
168
          swap(ary, end, 0);
169
          shiftDown(ary, 0, end - 1);
170
      }
171
  
172
      return ary;
173
  }
174
  
175
  function heapify(ary) {
176
      for (var start = (ary.length >> 1) - 1; start >= 0; start--) {
177
          shiftDown(ary, start, ary.length - 1);
178
      }
179
  }
180
  
181
  function shiftDown(ary, start, end) {
182
      var root = start,
183
          child, s;
184
  
185
      while (root * 2 + 1 <= end) {
186
          child = root * 2 + 1;
187
          s = root;
188
  
189
          if (ary[s] < ary[child]) {
190
              s = child;
191
          }
192
  
193
          if (child + 1 <= end && ary[s] < ary[child + 1]) {
194
              s = child + 1;
195
          }
196
  
197
          if (s !== root) {
198
              swap(ary, root, s);
199
              root = s;
200
          } else {
201
              return;
202
          }
203
      }
204
  }
205
  
206
  // Merge sort
207
  function merge_sort(ary) {
208
      if (ary.length <= 1) {
209
          return ary;
210
      }
211
  
212
      var m = ary.length >> 1;
213
  
214
      var left = ary.slice(0, m),
215
          right = ary.slice(m);
216
  
217
      return merge(merge_sort(left), merge_sort(right));
218
  }
219
  
220
  function merge(left, right) {
221
      var result = [],
222
          li = 0, ri = 0;
223
  
224
      while (li < left.length || ri < right.length) {
225
          if (li < left.length && ri < right.length) {
226
              if (left[li] <= right[ri]) {
227
                  result.push(left[li]);
228
                  li++;
229
              } else {
230
                  result.push(right[ri]);
231
                  ri++;
232
              }
233
          } else if (li < left.length) {
234
              result.push(left[li]);
235
              li++;
236
          } else if (ri < right.length) {
237
              result.push(right[ri]);
238
              ri++;
239
          }
240
      }
241
  
242
      return result;
243
  }
244
  
245
  // Shell sort
246
  function shell_sort(ary) {
247
      var inc = Math.round(ary.length / 2),
248
          i, j, t;
249
  
250
      while (inc > 0) {
251
          for (i = inc; i < ary.length; i++) {
252
              t = ary[i];
253
              j = i;
254
              while (j >= inc && ary[j - inc] > t) {
255
                  ary[j] = ary[j - inc];
256
                  j -= inc;
257
              }
258
              ary[j] = t;
259
          }
260
          inc = Math.round(inc / 2.2);
261
      }
262
  
263
      return ary;
264
  }
265
  //Comb Sort (Basically bubblesort with a small modification, but heaps faster)
266
function comb_sort(ary) {
267
    var gap = ary.length;
268
    while(true) {
269
        gap = newgap(gap);
270
        var swapped = false;
271
        for(var i=0,l=ary.length;i<l;i++) {
272
            var j = i + gap;
273
            if(ary[i] < ary[j]) {
274
                swap(ary,i,j);
275
                swapped = true;
276
            }
277
        }
278
        if(gap == 1 && !swapped)
279
             break;
280
    }
281
    return ary;   
282
}
283
function newgap(gap) {
284
    gap = ((gap * 10) / 13) | 0;
285
    if(gap == 9 || gap == 10)
286
        gap = 11;
287
    if(gap < 1)
288
         gap = 1;
289
    return gap;
290
}
291
//faster quicksort using a stack to eliminate recursion, sorting inplace to reduce memory usage, and using insertion sort for small partition sizes
292
function fast_quicksort(ary) {
293
    var stack = [];
294
    var entry = [0,ary.length,2 * Math.floor(Math.log(ary.length)/Math.log(2))];
295
    stack.push(entry);
296
    while(stack.length > 0) {
297
        entry = stack.pop();
298
        var start = entry[0];
299
        var end = entry[1];
300
        var depth = entry[2];
301
        if(depth == 0) {
302
         ary = shell_sort_bound(ary,start,end);
303
         continue;
304
        }
305
        depth--;
306
        var pivot = Math.round((start + end) / 2);
307
            
308
        var pivotNewIndex = inplace_quicksort_partition(ary,start,end, pivot);
309
        if(end - pivotNewIndex > 16) {
310
            entry = [pivotNewIndex,end,depth];
311
            stack.push(entry);
312
        }
313
        if(pivotNewIndex - start > 16) {
314
            entry = [start,pivotNewIndex,depth];
315
            stack.push(entry);
316
        }
317
    }
318
    ary = insertion_sort(ary);
319
    return ary;
320
}
321
function shell_sort_bound(ary,start,end) {
322
      var inc = Math.round((start + end)/2),
323
          i, j, t;
324
  
325
      while (inc >= start) {
326
          for (i = inc; i < end; i++) {
327
              t = ary[i];
328
              j = i;
329
              while (j >= inc && ary[j - inc] > t) {
330
                  ary[j] = ary[j - inc];
331
                  j -= inc;
332
              }
333
              ary[j] = t;
334
          }
335
          inc = Math.round(inc / 2.2);
336
      }
337
  
338
      return ary;
339
  }
340
341
function mSort(list) {
342
                if (list.length < 14) {
343
                    return insertion_sort(list);
344
                }
345
                
346
                var half = Math.floor(list.length / 2);
347
                var a = mSort(list.slice(0, half));
348
                var b = mSort(list.slice(half, list.length));
349
                var aCount = 0;
350
                var bCount = 0;
351
                var returnList = [];
352
                
353
                while (true) {
354
                    if (a[aCount] <= b[bCount]) {
355
                        returnList.push(a[aCount]);
356
                        aCount++;
357
                        if (aCount === a.length) {
358
                            returnList = returnList.concat(b.slice(bCount, b.length));
359
                            break;
360
                        }
361
                    }
362
                    else {
363
                        returnList.push(b[bCount]);
364
                        bCount++;
365
                        if (bCount === b.length) {
366
                            returnList = returnList.concat(a.slice(aCount, a.length));
367
                            break;
368
                        }
369
                    }
370
                }
371
                return returnList;
372
            }
373
  
374
  function bubbleSort(items) {
375
  var length = items.length;
376
  for (var i = 0; i < length; i++) { //Number of passes
377
    for (var j = 0; j < (length - i - 1); j++) { //Notice that j < (length - i)
378
      //Compare the adjacent positions
379
      if(items[j] > items[j+1]) {
380
        //Swap the numbers
381
        var tmp = items[j];  //Temporary variable to hold the current number
382
        items[j] = items[j+1]; //Replace current number with adjacent number
383
        items[j+1] = tmp; //Replace adjacent number with current number
384
      }
385
    }        
386
  }
387
}
388
  
389
  https://stackoverflow.com/a/38979903/8769328
390
  function radixBucketSort (arr) {
391
    var idx1, idx2, idx3, len1, len2, radix, radixKey;
392
    var radices = {}, buckets = {}, num, curr;
393
    var currLen, radixStr, currBucket;
394
395
    len1 = arr.length;
396
    len2 = 10;  // radix sort uses ten buckets
397
398
    // find the relevant radices to process for efficiency        
399
    for (idx1 = 0;idx1 < len1;idx1++) {
400
      radices[arr[idx1].toString().length] = 0;
401
    }
402
403
    // loop for each radix. For each radix we put all the items
404
    // in buckets, and then pull them out of the buckets.
405
    for (radix in radices) {          
406
      // put each array item in a bucket based on its radix value
407
      len1 = arr.length;
408
      for (idx1 = 0;idx1 < len1;idx1++) {
409
        curr = arr[idx1];
410
        // item length is used to find its current radix value
411
        currLen = curr.toString().length;
412
        // only put the item in a radix bucket if the item
413
        // key is as long as the radix
414
        if (currLen >= radix) {
415
          // radix starts from beginning of key, so need to
416
          // adjust to get redix values from start of stringified key
417
          radixKey = curr.toString()[currLen - radix];
418
          // create the bucket if it does not already exist
419
          if (!buckets.hasOwnProperty(radixKey)) {
420
            buckets[radixKey] = [];
421
          }
422
          // put the array value in the bucket
423
          buckets[radixKey].push(curr);          
424
        } else {
425
          if (!buckets.hasOwnProperty('0')) {
426
            buckets['0'] = [];
427
          }
428
          buckets['0'].push(curr);          
429
        }
430
      }
431
      // for current radix, items are in buckets, now put them
432
      // back in the array based on their buckets
433
      // this index moves us through the array as we insert items
434
      idx1 = 0;
435
      // go through all the buckets
436
      for (idx2 = 0;idx2 < len2;idx2++) {
437
        // only process buckets with items
438
        if (buckets[idx2] != null) {
439
          currBucket = buckets[idx2];
440
          // insert all bucket items into array
441
          len1 = currBucket.length;
442
          for (idx3 = 0;idx3 < len1;idx3++) {
443
            arr[idx1++] = currBucket[idx3];
444
          }
445
        }
446
      }
447
      buckets = {};
448
    }
449
  }
450
</script>
Script Preparation code:
 
var input = [];
for (var i = 0; i < 1000; i++) {
  input[i] = Math.round(Math.random() * 1000000);
}
Tests:
  • Built-in Sort

     
    builtin_sort(input.slice(0));
  • Naive Quicksort

     
    naive_quicksort(input.slice(0));
  • Inplace Quicksort

     
    inplace_quicksort(input.slice(0), 0, input.length);
  • Heap Sort

     
    heapSort(input.slice(0));
  • Merge Sort

     
    merge_sort(input.slice(0));
  • Shell Sort

     
    shell_sort(input.slice(0));
  • Comb Sort

     
    comb_sort(input.slice(0));
  • Insertion Sort

     
    insertion_sort(input.slice(0));
  • Fast QuickSort

     
    fast_quicksort(input.slice(0));
  • mSort

     
    mSort(input.slice(0));
  • Radix Bucket Sort

     
    radixBucketSort(input.slice(0)) 
  • Bubble Sort

     
    bubbleSort(input.slice(0));
  • My sort

     
    sortArray(input.slice(0));
Rendered benchmark preparation results:

Suite status: <idle, ready to run>

Previous results

Experimental features:

  • Test case name Result
    Built-in Sort
    Naive Quicksort
    Inplace Quicksort
    Heap Sort
    Merge Sort
    Shell Sort
    Comb Sort
    Insertion Sort
    Fast QuickSort
    mSort
    Radix Bucket Sort
    Bubble Sort
    My sort

    Fastest: N/A

    Slowest: N/A

Latest run results:
Run details: (Test run date: 3 years ago)
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.109 Safari/537.36 OPR/84.0.4316.50
Opera 84 on Windows
View result in a separate tab
Test name Executions per second
Built-in Sort 2587.0 Ops/sec
Naive Quicksort 1330.1 Ops/sec
Inplace Quicksort 19016.9 Ops/sec
Heap Sort 9889.0 Ops/sec
Merge Sort 2687.0 Ops/sec
Shell Sort 4908.9 Ops/sec
Comb Sort 5638.4 Ops/sec
Insertion Sort 1902.5 Ops/sec
Fast QuickSort 27711.7 Ops/sec
mSort 4249.2 Ops/sec
Radix Bucket Sort 2306.4 Ops/sec
Bubble Sort 567.9 Ops/sec
My sort 55.0 Ops/sec