C# 按代码点对字符数组排序最有效的方法是什么?(顺序排序)

C# 按代码点对字符数组排序最有效的方法是什么?(顺序排序),c#,.net,sorting,optimization,C#,.net,Sorting,Optimization,我希望尽可能高效地对字符数组进行排序,即以最小的CPU使用率、内存分配和垃圾收集开销进行排序。我天真的第一次尝试是这样一个简单的例子: 假设数组已经存在,例如 char[] word = "hello world".ToCharArray(); 优化这种天真的方法: Array.Sort(word, StringComparer.Ordinal); 事实上,我很惊讶这能起作用,因为它使用字符串比较器来比较字符,所以我怀疑比较器中正在进行从字符到字符串的转换,这在CPU使用率和垃圾收集等方面是

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

假设数组已经存在,例如

char[] word = "hello world".ToCharArray();
优化这种天真的方法:

Array.Sort(word, StringComparer.Ordinal);
事实上,我很惊讶这能起作用,因为它使用字符串比较器来比较字符,所以我怀疑比较器中正在进行从字符到字符串的转换,这在CPU使用率和垃圾收集等方面是次优的

假设我希望尽可能高效地执行这类操作,那么最好的方法是什么

现在,我的退路是使用以下内容:

List<char> wordChars = "hello world".ToList();
wordChars.Sort((char x, char y) => 
{
    return (int)x - (int)y;
});
不过,我不希望每个单词都有一个列表。另一个选择是编写自己的快速排序例程

顺便说一句,为了预防通常的一连串挑战-是的,我真的很想按代码点对字符数组进行排序,是的,我确实需要使其最优化!!越快越好。谢谢

这里的记录是一个强类型字符快速排序

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);
    }
}

List.Sort可能比您在短时间内能够编写的更好,它的工作原理如下:

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

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

否则,它将使用快速排序算法

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


值得一提的是,你需要问问自己什么是足够快的。显然,您觉得string.ToArray.Sort不够快是有原因的。这可能表明可能需要一种排序以外的方法。考虑到有限的细节,很难说。

发布您的基准代码和您想要实现的目标,以便我们知道如何避免必要的评论。我可以在比没有它的情况下编写基准代码更短的时间内完成这项工作。您如何知道哪一个更好。假设我贴了一个聪明的答案。你会仅仅因为一个陌生人的代码看起来不错就信任它吗?所以我很清楚,对于hello world,你的预期排序结果是Dehlloorw?@redcalx好的,让我们假设我说var s=helloworld.OrderByx=>x.ToArray;是最快的。你衡量它的标准是什么?@redcalx你分析过它吗?直觉可能并不总是正确的。也许排序算法非常快,创建一个新数组的成本很小,顺便说一句:我不是说这是正确的。我看到的是,你在等待某个权威人士说这样做,而没有显示出任何努力来衡量哪一个是真正正确的。谢谢。我的主要动机是避免任何装箱/强制转换,因为Array.Sort不是泛型的,StringComparer似乎没有任何基于字符的方法,这表明每个比较都是从字符强制转换到字符串。反省一下,我的问题更多的是要避免任何明显浪费的事情,像这样的事情很容易使用比强类型快速排序多10倍的CPU。有趣的是看到了内置排序的启发式方法-以前没有见过。如果使用基于linq的方法| new Stringgzdefghs3i.OrderByx=>x.ToArray |不应涉及StringComparer或装箱。OrderBy方法将使用默认的比较进行枚举和排序,=这是顺序的,取决于区域性/语言,它可能被视为字母排序,也可能不被视为字母排序。ToArray强制运行linq表达式,实际创建数组,字符串构造函数将数组复制到新字符串中。执行var x=gzdefghs3i.ToCharArray可能更快;x、 分类;分配更少