代码之家  ›  专栏  ›  技术社区  ›  We Are All Monica

算法:将列表从一个顺序重新排列到另一个顺序的最佳方法?

  •  6
  • We Are All Monica  · 技术社区  · 16 年前

    reorder(
      ['d', 'a', 'c', 'b', 'e'],
      ['a', 'b', 'c', 'd', 'e']
    )
    

    应该返回如下内容:

    [
      {move:'d', after:'b'},
      {move:'c', after:'b'}
    ]
    

    这表明我应该首先将元素“d”移动到“b”之后,然后将“c”移动到“b”之后,数组将按所需顺序排列。


    rtgui 到客户端,实际上)。现在我正在整理。基本上我有一个div列表,我想按任意顺序排序。我可以得到如下所需的订单:

    var hashes = {
      before: [],
      after: [],
    };
    var els = $('div.interesting-class').toArray();
    var len = els.length;
    
    for(var i = 0; i < len; i++) hashes.before.push(els[i].id);
    els.sort(getSortComparator());
    for(var i = 0; i < len; i++) hashes.after.push(els[i].id);
    

    hashes.before hashes.after 包含元素ID的无序和有序列表。在对列表重新排序时,到目前为止最昂贵的操作实际上是移动DOM元素。我一直在这样做:

    var c = $('#container-id');
    $(els).each(function() {
      c.append(this);
    });
    

    (在这种情况下,在 哈希斯 散列

    到目前为止,我已经尝试了几种通用的“diff”算法,但它们并没有真正满足我的需求。我想我需要的是这样,但更专业。

    4 回复  |  直到 15 年前
        1
  •  8
  •   Joel Nelson    16 年前

    http://en.wikipedia.org/wiki/Longest_increasing_subsequence

    查找最长的递增子序列(根据新的排序顺序)。然后将不在该序列中的每个元素移动到其相对于序列中已存在元素的位置。

    在您的示例中,“a,b,e”和“a,c,e”是最长的递增子序列。你所能做的就是选择其中一个,然后移动其他元素。

        2
  •  1
  •   Pointy    16 年前

    {和}将数组中的索引对象拆分为{个索引键。对该数组进行排序(当然,使用您可以使用的最佳排序;如果比较比较昂贵,则使用合并排序;如果比较便宜,则使用快速排序)。现在您知道了,从实际索引到排序数组以及存储在每个元素中的索引值,如何重新排列原始数组。

    对关键点进行排序后,“最佳”移动次数将是原始数组的O(n)。如果您想在适当的位置重新排列原始数组,那么可以非常简单地从已排序的索引列表中导出交换。

        3
  •  0
  •   Juan    16 年前

    我的第一个想法是你应该使用 Selection sort

        4
  •  0
  •   Jerry Coffin    16 年前

    Knuth第3卷有一节是关于“分类网络”的。他不会去参加一个聚会 经过证实的 最小化——它们试图最小化所需的比较器数量,但在实际实现真正的最小值方面并不一定成功。