JavaScript 中的基数排序

发布于 2024-09-25 11:06:09 字数 830 浏览 4 评论 0原文

我想出了以下方法,但可以预见的是它不起作用。

var t = new Array(a.length);
var r = 4;
var b = 64;

var count = new Array(1<<r);
var pref = new Array(1<<r);

var groups = Math.ceil(b / r);

var mask = (1 << r) - 1;

var shift = 0;
for(var c = 0; c < groups; c++)
{
    shift += r;

    for(var j = 0; j < count.length; j++)
    {
        count[j] = 0;
    }

    for(var i = 0; i < a.length; i++)
    {
        count[ (a[i] >> shift) & mask ]++;
    }

    pref[0] = 0;

    for(var i = 0; i < count.length; i++)
    {
        pref[i] = pref[i-1] + count[i-1];
    }

    for(var i = 0; i < a.length; i++)
    {
        t[ pref[ (a[i] >> shift) & mask ]++ ] = a[i];
    }

    for(var i = 0; i < a.length; i++)
    {
        a[i] = t[i];
    }
    // a is sorted?
}

I've come up with the following but it predictably doesn't work.

var t = new Array(a.length);
var r = 4;
var b = 64;

var count = new Array(1<<r);
var pref = new Array(1<<r);

var groups = Math.ceil(b / r);

var mask = (1 << r) - 1;

var shift = 0;
for(var c = 0; c < groups; c++)
{
    shift += r;

    for(var j = 0; j < count.length; j++)
    {
        count[j] = 0;
    }

    for(var i = 0; i < a.length; i++)
    {
        count[ (a[i] >> shift) & mask ]++;
    }

    pref[0] = 0;

    for(var i = 0; i < count.length; i++)
    {
        pref[i] = pref[i-1] + count[i-1];
    }

    for(var i = 0; i < a.length; i++)
    {
        t[ pref[ (a[i] >> shift) & mask ]++ ] = a[i];
    }

    for(var i = 0; i < a.length; i++)
    {
        a[i] = t[i];
    }
    // a is sorted?
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

梦初启 2024-10-02 11:06:09

这个循环基本上以一种更 JavaScript 的方式做同样的事情:

for (var div = 1, radix = 16; div < 65536 * 65536; div *= radix) {
  var piles = [];

  for (var i = 0; i < a.length; ++i) {
    var p = Math.floor(a[i] / div) % radix;
    (piles[p] || (piles[p] = [])).push(a[i]);
  }

  for (var i = 0, ai = 0; i < piles.length; ++i) {
    if (!piles[i]) continue;
    for (var pi = 0; pi < piles[i].length; ++pi)
      a[ai++] = piles[i][pi];
  }
}

这个循环不是像 C 程序员那样做,而是构建一个列表列表,每个可能的 4 位值都有一个列表。我避免使用位移运算符,因为这是 Javascript,虽然它们确实有效,但当数字变大时,事情就会变得有趣。

从“a”中每个值的低 4 位开始,代码将“a”的该元素复制到其中一个“堆”的末尾,即对应于 4 位值的堆。然后,它收集这些堆并从低 4 位为 0、然后为 1 等的所有值开始重建“a”。(显然会有一些间隙,因此会跳过这些间隙。)在每次迭代结束时在整个循环中,除数乘以基数,以便检查下一组 4 位。

一旦除数用完可用的整数范围,就完成了。

请注意,这仅适用于正数。用负数来做这件事有点奇怪;将负数剥离到单独的数组中,翻转符号,排序,然后反转可能会更容易。对正数进行排序,然后最后将反转的负数(再次翻转符号)粘贴到已排序的正数的前面。

This loop does basically the same thing, in a more Javascript-y way:

for (var div = 1, radix = 16; div < 65536 * 65536; div *= radix) {
  var piles = [];

  for (var i = 0; i < a.length; ++i) {
    var p = Math.floor(a[i] / div) % radix;
    (piles[p] || (piles[p] = [])).push(a[i]);
  }

  for (var i = 0, ai = 0; i < piles.length; ++i) {
    if (!piles[i]) continue;
    for (var pi = 0; pi < piles[i].length; ++pi)
      a[ai++] = piles[i][pi];
  }
}

Instead of doing it like a C programmer might, this loop builds a list of lists, one list for each possible 4-bit value. I avoid bit-shift operators because this is Javascript and while they do work, things get funny when numbers get large.

Starting with the low 4 bits of each value in "a", the code copies that element of "a" to the end of one of the "piles", that being the one corresponding to the 4-bit value. It then gathers up the piles and rebuilds "a" starting from all of the values whose low 4 bits were 0, then 1, etc. (Clearly there'll be some gaps, so those are skipped.) At the end of each iteration of the overall loop, the divisor is multiplied by the radix, so that the next set of 4 bits will be examined.

Once the divisor has exhausted the available range of integers, it's done.

Note that this will only work for positive numbers. Doing this with negative numbers gets a little weird; it might be easier to strip out the negative numbers into a separate array, flip the sign, sort, then reverse. Sort the positive numbers, and then finally glue the reversed negative numbers (flipping the signs again) to the front of the sorted positive numbers.

尬尬 2024-10-02 11:06:09

for(var i = 0; i < count.length; i++) 
{ 
    pref[i] = pref[i-1] + count[i-1]; 
} 

是一个问题,因为在第一次迭代中,i 为零,因此 pref[ 0 - 1 ] 不会很好地工作。

我没有方便的基数排序参考来确定您实际上应该在这里做什么。

this

for(var i = 0; i < count.length; i++) 
{ 
    pref[i] = pref[i-1] + count[i-1]; 
} 

is a problem because on the first iteration, i is zero and so pref[ 0 - 1 ] is not going to work very well.

I don't have a reference for radix sorts handy to determine what you should actually be doing here.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文