如何对字符串数组进行排序?

时间:2008-11-29 19:07:53

标签: c# arrays

我有一个用逗号分隔的输入单词列表。我想按字母和长度对这些单词进行排序。如何在不使用内置排序功能的情况下执行此操作?

8 个答案:

答案 0 :(得分:13)

好问题!!排序可能是作为一名崭露头角的计算机科学家学习的最重要的概念。

实际上有很多不同的算法可以对列表进行排序。

当你打破所有这些算法时,最基本的操作是比较列表中的两个项目,定义它们的“自然顺序”。

例如,为了对整数列表进行排序,我需要一个函数告诉我,给定任意两个整数X和Y,X是否小于,等于或大于Y.

对于你的字符串,你需要同样的东西:一个函数,它告诉你哪些字符串具有“较小”或“较大”的值,或者它们是否相等。

传统上,这些“比较器”功能看起来像这样:

int CompareStrings(String a, String b) {
   if (a < b)
      return -1;
   else if (a > b)
      return 1;
   else
      return 0;
}

我遗漏了一些细节(比如,你如何计算a是否小于或大于b?clue:迭代字符),但这是任何比较函数的基本框架。如果第一个元素较小,则返回小于零的值;如果第一个元素较大,则返回大于零的值;如果元素具有相等的值,则返回零。

但这与排序有什么关系呢?

排序路由将为列表中的元素对调用该函数,使用函数的结果来确定如何将项重新排列为排序列表。比较函数定义“自然顺序”,“排序算法”定义调用和响应比较函数结果的逻辑。

每个算法都像一个大图片策略,用于保证任何输入都能正确排序。以下是您可能想要了解的一些算法:

冒泡排序:

遍历列表,调用所有相邻元素对的比较函数。每当得到大于零的结果(意味着第一个元素大于第二个元素)时,交换这两个值。然后继续前进到下一对。当你到达列表的末尾时,如果你不必交换任何一对,那么恭喜,列表已经排序了!如果您必须执行任何交换,请返回到开头并重新开始。重复此过程,直到没有更多交换。

注意:这通常不是对列表进行排序的非常有效的方法,因为在最坏的情况下,对于包含N个元素的列表,可能需要扫描整个列表多达N次。

合并排序:

这是用于对列表进行排序的最流行的分治算法之一。基本思想是,如果你有两个已经排序的列表,很容易合并它们。从每个列表的开头开始,删除具有最小起始值的列表的第一个元素。重复这个过程,直到你消耗了两个列表中的所有项目,然后你就完成了!

1     4        8     10    
   2     5  7     9
------------ becomes ------------> 
1  2  4  5  7  8  9  10

但是如果你没有两个排序列表呢?如果您只有一个列表,并且其元素是随机顺序怎么办?

这是合并排序的聪明之处。您可以将任何单个列表分成更小的部分,每个部分都是未排序的列表,排序的列表或单个元素(如果你的话,它实际上是一个排序列表,长度为1)。

因此,合并排序算法的第一步是将整个列表划分为越来越小的子列表。在最小的级别(每个列表只有一个或两个元素),它们很容易排序。一旦排序,很容易将任何两个相邻的排序列表合并为一个更大的排序列表,其中包含两个子列表的所有元素。

注意:此算法 优于上面描述的冒泡排序方法,就其最坏情况场景效率而言。我不会详细解释(这涉及一些相当简单的数学,但需要一些时间来解释),但提高效率的快速原因是该算法将其问题分解为理想大小的块然后合并那些块的结果。冒泡排序算法立即解决了整个问题,因此它没有得到“分而治之”的好处。


这些只是用于排序列表的两种算法,但是还有很多其他有趣的技术,每种技术都有自己的优点和缺点:快速排序,基数排序,选择排序,堆排序,壳排序和桶排序。

互联网上充满了有关排序的有趣信息。这是一个很好的起点:

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

答案 1 :(得分:4)

创建一个控制台应用程序并将其粘贴到Program.cs中作为类的主体。

public static void Main(string[] args)
{
    string [] strList = "a,b,c,d,e,f,a,a,b".Split(new [] { ',' }, StringSplitOptions.RemoveEmptyEntries);

    foreach(string s in strList.Sort())
        Console.WriteLine(s);
}

public static string [] Sort(this string [] strList)
{
    return strList.OrderBy(i => i).ToArray();
}

请注意,我确实使用了内置方法OrderBy。正如其他答案所指出的那样,你可以在那里实现许多不同的排序算法,我认为除了实际的排序算法之外,我的代码片段为你做了一切。

Some C# specific sorting tutorials

答案 2 :(得分:2)

围绕sorting algorithms建立了整个研究领域。您可能想要选择一个简单的并实现它。

虽然它不是最高效的,但实施bubble sort不应花费太长时间。

答案 3 :(得分:0)

如果您不想使用内置函数,则必须自己创建一个。我建议冒泡排序或类似的算法。冒泡排序不是一种有效的算法,但它可以完成工作,并且易于理解。

你会在wikipedia找到很好的阅读。

答案 4 :(得分:0)

我建议为quicksort做一个wiki。

还不确定为什么你不想使用内置排序?

答案 5 :(得分:0)

冒泡排序会损害大脑。

插入排序至少要易于理解和编码,并且在实践中实际上很有用(对于非常小的数据集和接近排序的数据)。它的工作原理如下:

假设前n个项目已经按顺序排列(你可以从n = 1开始,因为显然有一件事本身就是“按照正确的顺序”)。

获取数组中的第(n + 1)项。称之为“枢轴”。从第n项开始并逐渐减少:
- 如果它大于枢轴,则将其向右移动一个空格(在其左侧创建“间隙”)。
- 否则,将它留在原位,将“枢轴”一个空格放在它的右边(也就是说,如果你移动任何东西,在“间隙”中,或者如果你什么都没移动就在它的位置),并停止。

现在数组中的前n + 1项是有序的,因为枢轴位于比它小的所有东西的右边,并且位于比它大的所有东西的左边。既然你按顺序开始了n个项目,那就是进步。

重复,每步增加1,直到你处理完整个列表为止。

这对应于一种方法,您可以将一系列文件夹按顺序放入文件柜中:放入一个;然后通过将其后的所有东西推到一个空间以腾出空间,将另一个放入正确的位置;重复直到完成。没有人通过冒泡排序对物理对象进行排序,因此对我来说,为什么它被认为是“简单”是一个谜。

现在剩下的就是你需要能够解决两个字符串,第一个是大于第二个。我不太确定“字母和长度”的含义:字母顺序是通过每次比较一个字符来完成的。如果不一样,那就是你的订单。如果它们是相同的,请查看下一个,除非你的一个字符串中没有字符,在这种情况下,那是“较小”的字符。

答案 6 :(得分:0)

使用NSort

几年前,我在NSort一书中遇到了Windows Developer Power Tools图书馆。 NSort库实现了许多排序算法。使用NSort之类的东西而不是编写自己的排序的主要优点是已经过测试和优化。

答案 7 :(得分:0)

在C#中发布快速字符串排序代码的链接:

http://www.codeproject.com/KB/cs/fast_string_sort.aspx

另一点: 建议不要将上述建议的比较用于非英语语言:

int CompareStrings(String a,String b){
if(a&lt; b)返回-1;
否则如果(a> b)
返回1;否则
返回0; }

查看此链接以获取非英语语言排序:

http://msdn.microsoft.com/en-us/goglobal/bb688122

如上所述,将nsort用于不适合内存的巨大数组。