【问题标题】:How can I sort an array of strings?如何对字符串数组进行排序?
【发布时间】:2008-11-29 19:07:53
【问题描述】:

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

【问题讨论】:

  • 您希望它们如何排序?按字母顺序?通过字符串的长度?不然呢?
  • 为什么(除了家庭作业)你想在不使用任何内置函数的情况下这样做?
  • @Jon ...也许是因为知道如何实现排序例程是学习如何设计自己的算法的第一步。音乐会钢琴家一般不会为观众演奏“玛丽有只小羊羔”,但大多数人都是这样开始学习的。
  • :-) 练习我已经完成的功能(第一个:将每个单词的第一个字母大写,2ed 反向顺序....等等......但我被困住了在网上做了一些研究,但我仍然找不到它)

标签: c# arrays


【解决方案1】:

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

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

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

例如,为了对整数列表进行排序,我需要一个函数来告诉我,给定任意两个整数 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?线索:遍历字符),但这是任何比较函数的基本框架。如果第一个元素较小,则返回小于零的值,如果第一个元素较大,则返回大于零的值,如果元素具有相等的值,则返回零。

但这与排序有什么关系?

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

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

冒泡排序:

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

注意:这通常不是对列表进行排序的一种非常有效的方法,因为在最坏的情况下,它可能需要您扫描整个列表多达 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 提供有价值的内容而不提供“剪切和粘贴”解决方案
【解决方案2】:

创建一个控制台应用程序并将其粘贴到 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。正如其他答案指出的那样,您可以在那里实现许多不同的排序算法,我认为我的代码 sn-p 可以为您完成所有工作,除了实际的排序算法。

Some C# specific sorting tutorials

【讨论】:

  • OP 想写一个排序算法而不是使用内置的。
  • “这个字符串[] strList”是什么意思?
  • 雷蒙德,我知道。虽然它是它自己的功能:)。 Sara 可以用她自己的排序实现来填写该扩展方法的主体,她会很高兴。我不想做所有的工作。
  • Raymond,我更新说明了我为什么使用内置函数。
【解决方案3】:

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

虽然它不会是最高性能的,但实现bubble sort 应该不会花费您太长时间。

【讨论】:

    【解决方案4】:

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

    您会在wikipedia 上找到很多不错的读物。

    【讨论】:

    • 维基百科在我的国家被屏蔽
    • 哇,那是哪个国家?中国?
    【解决方案5】:

    我建议为快速排序创建一个 wiki。

    仍然不确定为什么不想使用内置排序?

    【讨论】:

      【解决方案6】:

      冒泡排序会损害大脑。

      插入排序至少与理解和编码一样简单,并且在实践中实际上很有用(对于非常小的数据集和几乎排序的数据)。它的工作原理是这样的:

      假设前 n 项已经按顺序排列(您可以从 n = 1 开始,因为很明显,只有一件事是“按正确顺序排列”)。

      获取数组中的第 (n+1) 个项目。将此称为“枢轴”。从第 n 个项目开始并逐步完成:
      - 如果它大于枢轴,将其向右移动一个空间(以在其左侧创建一个“间隙”)。
      - 否则,将其留在原处,将“枢轴”放在其右侧一个空间(即,如果您移动任何东西,则在“间隙”中,或者如果您什么都不移动,则在它开始的地方),然后停止。

      现在数组中的前 n+1 项是有序的,因为枢轴位于比它小的所有元素的右侧,以及大于它的所有元素的左侧。既然你开始按顺序排列 n 个项目,那就是进步。

      重复,每一步 n 增加 1,直到处理完整个列表。

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

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

      【讨论】:

        【解决方案7】:

        使用 NSort

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

        【讨论】:

          【解决方案8】:

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

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

          还有一点: 上面建议的比较器不推荐用于非英语语言:

          int CompareStrings(String a, String b) {
          如果 (a 否则如果 (a > b)
          返回 1;其他
          返回0; }

          查看此链接以了解非英语语言:

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

          如前所述,将 nsort 用于无法放入内存的非常巨大的数组。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2014-07-05
            • 2016-07-18
            • 2011-03-10
            • 1970-01-01
            • 2020-05-29
            相关资源
            最近更新 更多