【问题标题】:Radix Sort in JavaScriptJavaScript 中的基数排序
【发布时间】:2010-09-28 21:07:10
【问题描述】:

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

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?
}

【问题讨论】:

  • a 保存输入的整数数组?为什么不将countprefgroups 归零? JS 中的数组,即使是通过new Array(length) 创建的数组也以未定义的内容开头,而undefined + 0NaN
  • @Mike:首先,我什至不太确定这种 supposed 是如何工作的,因此我不确定出了什么问题。 count 已清零,pref 在使用前已初始化,groups 不是数组。
  • 基数排序通过查看排序键的片段进行排序,片段足够小,以至于片段的所有可能值都可以描述可管理数量的离散列表。想象一下对您的 CD 收藏进行分类:首先按艺术家姓名的第二个字母制作一堆,然后通过 A - Z 堆,并按第一个字母制作新的一堆。当您再次捡起 A - Z 堆并在架子上从左到右排列时,它们就被分类了!
  • 能否提供样例输入输出?
  • 一个问题是“b”似乎代表每个整数的位大小,这对于 Javascript 来说是错误的值。 Javascript 整数只有 32 位(或 31 位)。

标签: javascript sorting radix-sort


【解决方案1】:

这个循环基本上做同样的事情,以更 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 位。

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

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

【讨论】:

  • 这行得通,我会把它拆开,看看能不能把头包起来。我想在我的一些代码中实现这种类型,我是否有您的许可?
  • 当然;这是很常见的东西。我很喜欢你的问题,因为我一直试图让我的一个孩子对基数排序我的旧 LP 收藏的前景感到兴奋:-)
【解决方案2】:

这个

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

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

我没有关于基数排序的参考资料,可以方便地确定你应该在这里实际做什么。

【讨论】:

  • “pref”数组用于保存每个基数存储桶的值计数。如果我用 Javascript 来做,我根本不会那样做;它就像一个转录的 C 程序。
  • @Pointy:我从 C# 实现中得到了几乎逐字记录的代码。可能是为什么它看起来像是转录的。 ;)
猜你喜欢
  • 2016-07-30
  • 2020-04-14
  • 1970-01-01
  • 2016-10-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-31
  • 2016-09-10
相关资源
最近更新 更多