最有效的方法是通过代码点对char数组进行排序? (序数排序)

时间:2015-08-05 21:05:01

标签: c# .net sorting optimization

我希望尽可能高效地对char数组进行排序,即CPU使用率最低,内存分配和垃圾收集开销。我天真的第一次尝试就是这个简单的例子:

假设数组已存在,例如

char[] word = "hello world".ToCharArray();

优化这种天真的方法:

Array.Sort(word, StringComparer.Ordinal);

实际上我很惊讶这是有效的,因为它使用字符串比较器来比较字符,所以我怀疑在比较器内部有一个从char转换为字符串的转换,这在CPU使用率方面是次优的。垃圾收集等。

假设我想尽可能高效地执行此类操作,最佳方法是什么?

现在我的后退是使用类似的东西:

List<char> wordChars = "hello world".ToList();
wordChars.Sort((char x, char y) => 
{
    return (int)x - (int)y;
});

我宁愿不为每个单词留下List的开销。另一个选择是编写我自己的快速排序程序!

P.S。为了预防通常的挑战 - 是的,我确实想要通过代码点对char数组进行排序,是的,我确实需要让它达到最佳状态!越快越好。谢谢!

这里的记录是一个强类型的char快速排序......

public static class CharSort
{
    public static void QuickSort(char[] arr)
    {
        QuickSort(arr, 0, arr.Length - 1);
    }

    private static void QuickSort(char[] arr, int left, int right)
    {
        do
        {
            int p = left;
            int q = right;
            char val = arr[p + (q - p >> 1)];
            do
            {
                if(p < arr.Length)
                {
                    if(val - arr[p] > 0)
                    {
                        p++;
                        continue;
                    }
                }
                while (q >= 0 && (val - arr[q] < 0)) 
                {
                    q--;
                }

                if(p > q) {
                    break;
                }

                if(p < q)
                {
                    char num3 = arr[p];
                    arr[p] = arr[q];
                    arr[q] = num3;
                }
                p++;
                q--;
            }
            while(p <= q);
            if(q - left <= right - p)
            {
                if(left < q) {
                    QuickSort(arr, left, q);
                }
                left = p;
            }
            else
            {
                if(p < right) {
                    QuickSort(arr, p, right);
                }
                right = q;
            }
        }
        while(left < right);
    }
}

1 个答案:

答案 0 :(得分:1)

List.Sort可能比你在短时间内写的更好,它的工作原理如下 [see]

  • 如果分区大小少于16个元素,则使用插入 排序算法。

  • 如果分区数超过2 * LogN,则其中N是范围 在输入数组中,它使用了Heapsort算法。

  • 否则,它使用Quicksort算法。

我想,简单地计算每个字符的出现可能会更快,但这可能会因Unicode代码点(代理对)而变得棘手。如果你所关心的只是普通英文字符(ASCII范围),你可以只分配一个字符范围大小的数组(127),使用字符值作为索引和增量循环到字符串。如果你真的需要实际的字符串,你可以通过创建一个字符串缓冲区并用索引顺序填充每个非零字符计数的计数来重构它。

值得一提的是,您需要问自己什么是“足够快”。显然,你有一个理由认为“string”.ToArray()。Sort()不够快。这可能表明可能需要一种非排序的方法。鉴于细节有限,很难说。