Skip to content

Instantly share code, notes, and snippets.

@ideawu
Last active June 29, 2021 08:29
Show Gist options
  • Star 43 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save ideawu/a114679bb8f0a94452d462ae14b7c977 to your computer and use it in GitHub Desktop.
Save ideawu/a114679bb8f0a94452d462ae14b7c977 to your computer and use it in GitHub Desktop.
快速排序QuickSort算法JavaScript实现, 包括 Hoare 和 Lomuto 版本的实现,以及网友实现版本的对比
<html>
<body>
<script>
// @author: ideawu
// @link: http://www.ideawu.net/blog/archives/1021.html
var swap_count = 0;
var cmp_count = 0;
// https://gist.github.com/wintercn/c30464ed3732ee839c3eeed316d73253
function wintercn_qsort(arr, start, end){
var midValue = arr[start];
var p1 = start, p2 = end;
while(p1 < p2) {
swap(arr, p1, p1 + 1);
while(compare(arr[p1], midValue) >= 0 && p1 < p2) {
swap(arr, p1, p2--);
}
p1 ++;
}
if(start < p1 - 1)
wintercn_qsort(arr, start, p1 - 1);
if(p1 < end)
wintercn_qsort(arr, p1, end);
}
// http://www.ruanyifeng.com/blog/2011/04/quicksort_in_javascript.html
var ruanyifeng_qsort = function(arr) {
if (arr.length <= 1) { return arr; }
var pivotIndex = Math.floor(arr.length / 2);
var pivot = arr.splice(pivotIndex, 1)[0];
swap_count++;
var left = [];
var right = [];
for (var i = 0; i < arr.length; i++){
if (compare(arr[i], pivot) < 0) {
swap_count++;
left.push(arr[i]);
} else {
swap_count++;
right.push(arr[i]);
}
}
swap_count++;
return ruanyifeng_qsort(left).concat([pivot], ruanyifeng_qsort(right));
}
function compare(a, b){
cmp_count ++;
return a-b;
}
function swap(arr, s, e){
swap_count ++;
var tmp = arr[s];
arr[s] = arr[e];
arr[e] = tmp;
}
function partition_hoare(arr, start, end){
var pivot = arr[start];
var s = start;
var e = end;
while(1){
while(compare(arr[s], pivot) < 0){
s ++;
}
while(compare(arr[e], pivot) > 0){
e --;
}
if(s == e){
return s;
}else if(s > e){
return s-1;
}
swap(arr, s, e);
s++;
e--;
}
}
function qsort_hoare(arr, start, end){
if(start >= end){
return;
}
var p = partition_hoare(arr, start, end);
qsort_hoare(arr, start, p);
qsort_hoare(arr, p+1, end);
}
function partition_lomuto(arr, start, end){
var pivot = arr[end];
var s = start;
for(var g = start; g < end; g++){
if(compare(arr[g], pivot) < 0){
if(s != g){
swap(arr, s, g);
}
s ++;
}
}
if(s == end){
return s-1;
}else{
swap(arr, s, end);
return s;
}
}
function qsort_lomuto(arr, start, end){
if(start >= end){
return;
}
// console.log('in', arr, start, end);
var p = partition_lomuto(arr, start, end);
// console.log(JSON.stringify(arr.slice(start, p+1)), JSON.stringify(arr.slice(p+1, end+1)));
qsort_lomuto(arr, start, p);
qsort_lomuto(arr, p+1, end);
}
function bubble_sort(arr, start, end){
for(var i=start; i<=end; i++){
for(var j=start; j<=end-i-1; j++){
if(compare(arr[j], arr[j+1]) > 0){
swap(arr, j, j+1);
}
}
}
}
function check_result(a){
var pass = true;
var v = a[0];
for(var j=0; j<a.length; j++){
var n = a[j];
if(n < v){
pass = false;
break;
}
v = a[j];
}
return pass;
}
function run_test(func, name){
document.write('<b>run test: ', name, '</b><br/>');
swap_count = 0;
cmp_count = 0;
var nlogn = 0;
var stime = (new Date()).getTime();
for(var i=1; i<=arr.length; i++){
var a = arr.slice(0, i);
var b = func(a, 0, a.length - 1);
if(func == ruanyifeng_qsort){
a = b;
}
if(!check_result(a)){
console.log(i, 'fail');
console.log(a);
}
nlogn += Math.floor(i*Math.log(i));
// console.log('n:', i, 'swaps:', swap_count, 'compares:', cmp_count, 'nlogn:', Math.floor(i*Math.log(i)), JSON.stringify(a));
}
var etime = (new Date()).getTime();
document.write('time: ', etime-stime, ' ms', '<br/>');
document.write('compare: ', cmp_count, ' swap: ', swap_count, ' nlogn: ', nlogn, '<br/>');
document.write('<br/>');
}
var count = 2000;
var arr = [];
for(var i=0; i<count; i++){
arr.push(Math.floor(Math.random() * count));
}
console.log('datasource:', JSON.stringify(arr));
document.write('Running...');
setTimeout(function(){
document.write('<pre>');
run_test(wintercn_qsort, 'wintercn_qsort');
run_test(ruanyifeng_qsort, 'ruanyifeng_qsort');
run_test(qsort_hoare, 'qsort_hoare');
run_test(qsort_lomuto, 'qsort_lomuto');
document.write('</pre>');
// document.write('Running bubble_sort...');
// setTimeout(function(){
// document.write('<pre>');
// run_test(bubble_sort, 'bubble_sort');
// document.write('</pre>');
// }, 0);
}, 0);
</script>
</body>
</html>
@shiye515
Copy link

shiye515 commented May 12, 2018

耗时排名稳定在第一或者第二的位置,weibo:光挣钱不说话

function shiye515Sort(arr, start, end) {
  let divider = end;
  let dividerValue = arr[divider]
  let blank = divider
  let pickStart = start
  let pickEnd = end - 1
  let isAsc = true
  while (pickStart <= pickEnd) {
    if (isAsc) {
      if (compare(arr[pickStart], dividerValue) > 0) {
        swap(arr, blank, pickStart);
        blank = pickStart
        isAsc = false
      }
      pickStart++
    } else {
      if (compare(arr[pickEnd], dividerValue) < 0) {
        swap(arr, blank, pickEnd);
        blank = pickEnd
        isAsc = true
      }
      pickEnd--
    }
  }
  let mid = isAsc ? (pickEnd + 1) : (pickStart - 1)
  if (start < mid - 1) {
    shiye515Sort(arr, start, mid - 1)
  }
  if (mid + 1 < end) {
    shiye515Sort(arr, mid + 1, end)
  }
}

@yyssjj33
Copy link

为啥没人提到要先shuffle下?quicksort最坏复杂度不是O^2吗?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment