好问题!!作为一名崭露头角的计算机科学家,排序可能是最重要的概念。
实际上有很多不同的算法可以对列表进行排序。
当您分解所有这些算法时,最基本的操作是比较列表中的两个项目,定义它们的“自然顺序”。
例如,为了对整数列表进行排序,我需要一个函数来告诉我,给定任意两个整数 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