用于排序子序列的最有效排序算法

时间:2012-05-04 13:46:09

标签: c# algorithm sorting quicksort mergesort

我有几个类型为long(升序)的数字排序序列,并希望生成一个包含相同顺序的所有元素的主序列。我寻找最有效的排序算法来解决这个问题。我的目标是C#,。Net 4.0,因此也欢迎针对并行性的想法。

这是一个例子:
s1 = 1,2,3,5,7,13
s2 = 2,3,6
s3 = 4,5,6,7,8
得到的序列= 1,2,2,3,3,4,5,5,6,6,7,7,8,13

编辑:当有两个(或更多)相同的值时,那两个(或更多)的顺序无关紧要。

5 个答案:

答案 0 :(得分:4)

只需合并序列。您无需再次对它们进行排序。

答案 1 :(得分:4)

我知道没有.NET Framework方法可以进行K-way合并。通常,它使用优先级队列(通常是堆)完成。这并不困难,而且效率很高。给定K个排序列表,一起保存N个项目,复杂度为O(N log K)。

我在文章A Generic Binary Heap Class中展示了一个简单的二进制堆类。在Sorting a Large Text File中,我将介绍多个已排序子文件的创建,并使用堆来执行K-way合并。考虑一小时(也许更少)的学习,你可以适应你的课程。

答案 2 :(得分:2)

您必须像合并排序一样合并序列。

这可以并行化:

  1. 合并序列(1/2中的1和2),(3/4中的3和4),...
  2. 合并序列(1/2/3/4 in 1/2/3/4),(5/6和7/8 in 5/6/7/8),...
  3. ...
  4. 这是合并功能:

    int j = 0;
    int k = 0;
    for(int i = 0; i < size_merged_seq; i++)
    {
      if (j < size_seq1 && seq1[j] < seq2[k])
      {
        merged_seq[i] = seq1[j];
        j++;
      }
      else
      {
        merged_seq[i] = seq2[k];
        k++;
      }
    }
    

答案 3 :(得分:2)

简单的方法是逐个将它们相互合并。但是,这需要O(n*k^2)时间,其中k是序列数,n是序列中的平均项数。但是,使用分而治之的方法可以将此时间降低到O(n * k * log k)。算法如下:

  1. 将k个序列分为k / 2个组,每个2个元素(如果k为奇数,则为1个1元素组)。
  2. 合并每组中的序列。因此,您将获得k / 2个新组。
  3. 重复直到获得单个序列。

答案 4 :(得分:1)

更新:

事实证明,使用所有算法......简单的方法仍然更快:

private static List<T> MergeSorted<T>(IEnumerable<IEnumerable<T>> sortedBunches)
{
    var list = sortedBunches.SelectMany(bunch => bunch).ToList();

    list.Sort();

    return list;
}

为了传统目的......

以下是优先排序的最终版本:

    private static IEnumerable<T> MergeSorted<T>(IEnumerable<IEnumerable<T>> sortedInts) where T : IComparable<T>
    {
        var enumerators = new List<IEnumerator<T>>(sortedInts.Select(ints => ints.GetEnumerator()).Where(e => e.MoveNext()));

        enumerators.Sort((e1, e2) => e1.Current.CompareTo(e2.Current));

        while (enumerators.Count > 1)
        {
            yield return enumerators[0].Current;

            if (enumerators[0].MoveNext())
            {
                if (enumerators[0].Current.CompareTo(enumerators[1].Current) == 1)
                {
                    var tmp = enumerators[0];
                    enumerators[0] = enumerators[1];
                    enumerators[1] = tmp;
                }
            }
            else
            {
                enumerators.RemoveAt(0);
            }
        }

        do
        {
            yield return enumerators[0].Current;
        } while (enumerators[0].MoveNext());
    }