【问题标题】:Coding the QuickSort algorithm - output not quite right编码快速排序算法 - 输出不太正确
【发布时间】:2012-07-23 04:53:17
【问题描述】:

不幸的是,我以前从未亲自编写过此代码。我的实现在基于对“日期”字段进行排序的自定义类上运行。是的,我完全知道我可以使用内置的 Javascript 排序并指定比较器函数,但这不是我感兴趣的。

目前我从一个反向排序的列表开始,然后在调用我的“target_sort”(快速排序)之后,我得到一个排序不太好的列表。

代码:

function target_sort_wrapper(array) {
    target_sort(array, array.length, 0, array.length);
}


//Quicksort to swap around targets based on dates
//"array" is DDATA, where DDATA[i] are targets
function target_sort(array, length, left, right) {
    if (length < 2) {
        return;
    }
    var pivotIndex = choosePivot(array, length); //returns the index    

    partition(array, pivotIndex, left, right);

    target_sort(array, pivotIndex, 0, pivotIndex - 1);
    target_sort(array, pivotIndex, pivotIndex + 1, array.length);

}

function partition(array, pivotIndex, left, right) {
    //first, put the pivot as the first element to make things easier
    array.swap(pivotIndex, 0);
    var pivot = array[0];
    var i = left + 1;
    for (var j = left + 1; j < right; j++) {
        if (dateValue(array[j].date) < dateValue(pivot.date)) {
            //dateValue converts stuff like "Jun18" into 618, to numerically compare
            array.swap(i, j);
            i = i + 1;
        }
    }
    //don't forget to put pivot back where it belongs
    array.swap(left, i - 1);
}

function choosePivot(array, length) {
    return Math.floor(Math.random() * length); //0 (inclusive) to length (exclusive) 
}

    Array.prototype.swap = function (i, j) {
        var temp = this[i];
        this[i] = this[j];
        this[j] = temp;
        return this;
    }

这是输出。首先打印反向排序的列表,然后是我的“target_sort”的结果:

Jul06 Jul06 Jul06 Jul06 Jul06 Jul06 Jul06 Jul06 Jul06 Jul06 Jul06 Jul06 Jul06 Jul06 Jul06 Jul06 Jul06 Jul06 Jul06 Jul06 Jul06 Jul06 Jul06 Jul06 Jul06 Jul06 Jul06 Jul06 Jul06 Jul06 Jul06 Jul06 Jul05 Jul05 Jul05 Jul05 Jul05 Jul05 Jul05 Jul05 Jul05 Jul05 Jul05 Jul05 Jul05 Jul05 Jul05 Jul05 Jul05 Jul05 Jul05 Jul05 Jul05 Jul05 Jul05 Jul05 Jul05 Jul05 Jul05 Jul05 Jul05 Jul05 Jul05 Jul05 Jun25 Jun25 Jun25 Jun25 Jun25 Jun25 Jun25 Jun25 Jun25 Jun25 Jun25 Jun25 Jun25 Jun25 Jun25 Jun25 Jun25 Jun25 Jun25 Jun25 Jun25 Jun25 Jun25 Jun25 Jun25 Jun25 Jun19 Jun19 Jun19 Jun19 Jun19 Jun19 Jun19 Jun19 Jun19 Jun19 Jun19 Jun19 Jun19 Jun19 Jun19 Jun19 Jun19 Jun19 Jun19 Jun19 Jun19 Jun19 Jun19 Jun19 Jun19 Jun19 Jun19 Jun19 Jun19 Jun19 Jun19 Jun19 
============================================================= 
Jun19 Jun19 Jun19 Jun19 Jun19 Jun19 Jun19 Jun19 Jun19 Jun19 Jun19 Jun19 Jun19 Jun19 Jun19 Jun25 Jun19 Jun19 Jun19 Jun19 Jun19 Jun19 Jun19 Jun19 Jun19 Jun19 Jun19 Jun19 Jun19 Jun19 Jun19 Jun19 Jun19 Jun25 Jun25 Jun25 Jul05 Jun25 Jul05 Jul05 Jul05 Jul05 Jul05 Jul05 Jul05 Jul05 Jul05 Jul05 Jul05 Jul05 Jul05 Jul05 Jul05 Jul05 Jul05 Jul05 Jul05 Jul05 Jul05 Jul05 Jul05 Jul05 Jul05 Jul05 Jul06 Jul06 Jul06 Jul06 Jul06 Jul06 Jul06 Jul06 Jul06 Jul06 Jun25 Jul06 Jun25 Jun25 Jun25 Jun25 Jun25 Jun25 Jun25 Jun25 Jun25 Jun25 Jun25 Jun25 Jun25 Jun25 Jul06 Jul06 Jun25 Jul06 Jun25 Jun25 Jun25 Jun25 Jul05 Jun25 Jul05 Jul06 Jul06 Jul06 Jul06 Jul06 Jul06 Jul06 Jul06 Jul06 Jul06 Jul06 Jul06 Jul06 Jul06 Jul06 Jul06 Jul06 Jul05 Jul05 Jul05 Jul06  

我觉得它快到了,但仍有一些问题。

我已经被困了几天了,非常感谢您的帮助。

干杯。

【问题讨论】:

  • 您可以在 codereview 查看此代码。
  • 什么是代码审查?是不是更适合问我的问题?
  • 确保合并按预期进行。
  • @YoungMoney 是的。他们可以在那里验证您的代码。 codereview.stackexchange.com
  • @Desolator:CodeReview 适用于您希望查看是否可以改进的工作代码。这段代码工作,所以 StackOverflow 是它的合适站点。

标签: javascript algorithm sorting quicksort


【解决方案1】:

递归调用中断:

target_sort(array, pivotIndex, 0, pivotIndex - 1);

一个明显的事情是您将pivotIndex 作为两个分区的长度传递,这没有任何意义。

另一个是索引被破坏了。如您所见,左侧索引为0,但如果您在第二个递归级别并想要获取上级右分区的左分区,则显然不是这样。

还有一件事:枢轴选择器不必知道数组:

function choosePivot(length)

提示:编程不是猜谜游戏,在开始之前,请确定“变量”的确切含义。什么是长,左,右?例如:正确的索引是否包含在内(它是指向分区的一部分还是刚好超出它)。然后挑选一张纸和铅笔,找出合适的索引和长度。相信我,你想得越仔细,你就会越快完成。调试会浪费很多时间。然后,为了验证您是否走在正确的轨道上,请使用一个小玩具数组来实现,并添加一些 console.log 消息以查看发生了什么。

【讨论】:

  • 感谢您的意见。所以右半递归调用应该有长度(array.length - pivotIndex - 1)我认为,只是从画出来。但是现在我收到错误“递归过多”并且程序崩溃。如果不是 0,我不确定左索引应该是什么?
  • 最后一个问题:那么,分区的左索引是多少?另请参阅更新。
  • 就是这样,我想我想调用快速排序的左半部分总是从 0 到我的旧 pivotIndex...
【解决方案2】:

我现在已经创建了一个正确的版本,感谢 Karoly 的提示。总结:

  • 不应该做关于长度的事情,而是左右分开
  • 我总是为递归调用选择一个错误的枢轴(同样,必须左右,并且必须在子数组的正确范围内)

代码:

function target_sort_wrapper(array) {
    target_sort(array, 0, array.length);
}


//Quicksort to swap around targets based on dates
//"array" is DDATA, where DDATA[i] are targets
function target_sort(array, left, right) {
    if ((right-left) < 2) {
        return;
    }

    var pivotIndex = choosePivot(left, right); //returns the index  

    pivotIndex = partition(array, pivotIndex, left, right);

    target_sort(array, left, pivotIndex);
    target_sort(array, pivotIndex+1, right);

}

function partition(array, pivotIndex, left, right) {
    //first, put the pivot as the first element to make things easier
    var pivot = array[pivotIndex];
    array.swap(pivotIndex, left);
    var i = left + 1; 
    for(var j = left + 1; j < right; j++) {
        //if (array[j] > pivot) { } //do nothing, satisfies invariant
        if (dateValue(array[j].date) < dateValue(pivot.date)) {
        //if (array[j] < pivot) {
            array.swap(i, j);
            i = i + 1; 
        }
    }
    //don't forget to put pivot back where it belongs
    array.swap(left, i-1);
    return (i-1);
}

function choosePivot(left, right) {
    return (left + Math.floor(Math.random() * (right-left)));

}

Array.prototype.swap = function(i, j) {
    var temp = this[i];
    this[i] = this[j];
    this[j] = temp;
    return this;
}

【讨论】:

    猜你喜欢
    • 2015-06-12
    • 1970-01-01
    • 1970-01-01
    • 2016-02-28
    • 1970-01-01
    • 1970-01-01
    • 2016-11-24
    • 2018-05-17
    • 1970-01-01
    相关资源
    最近更新 更多