我很好奇,为什么排序算法中的稳定性如此重要或不重要?
我很好奇,为什么排序算法中的稳定性如此重要或不重要?
如果一个排序算法可以满足如下条件,即排序后相同关键字的两个对象的顺序与它们在输入数组中出现的顺序相同,则称该算法是稳定的。像插入排序、归并排序、冒泡排序等一些排序算法天生就是稳定的。而像堆排序、快速排序等一些排序算法则不是。
背景信息:一个“稳定的”排序算法能够保持具有相同排序关键字的元素原来的顺序。假设我们有一个由五个字母单词组成的列表:
peach
straw
apple
spork
如果我们只根据每个单词的首字母对列表进行排序,那么稳定排序将产生:
apple
peach
straw
spork
在不稳定的排序算法中,可能会交换 straw
或 spork
的位置,但在稳定的算法中,它们保持相对位置不变(也就是说,由于 straw
在输入中出现在 spork
之前,它在输出中也会出现在 spork
之前)。排序的稳定性意味着具有相同键的记录在排序前后保留它们的相对顺序。
因此,只有当解决的问题需要保留相对顺序时,稳定性才很重要。
如果不需要稳定性,可以使用库中的快速、内存占用少的算法,如堆排序或快速排序,并忘记它。
如果需要稳定性,则更加复杂。稳定算法比不稳定算法具有更高的大O CPU和/或内存使用率。因此,当您有一个大数据集时,必须在CPU和内存之间进行选择。如果CPU和内存都受限制,则会出现问题。一个很好的折衷稳定算法是二叉树排序; Wikipedia文章基于STL提供了一个非常简单的C++实现。
您可以通过将原始记录号添加为每个记录的最后一个键来将不稳定的算法变成稳定的算法。
这取决于你的操作。
假设你有一些人员记录,其中包含名字和姓氏字段。首先按照名字字段对列表进行排序,然后使用稳定的算法按照姓氏字段再次排序,这样你就得到了一个既按名字排序又按姓氏排序的列表。
稳定性的重要性有几个方面。其中之一是,如果两条记录不需要被交换,那么通过交换它们,可能会导致内存更新,页面被标记为脏页,并且需要重新写入磁盘(或其他慢速媒介)。
References: http://www.math.uic.edu/~leon/cs-mcs401-s08/handouts/stability.pdf http://en.wikipedia.org/wiki/Sorting_algorithm#Stability
PS: 当然,两次排序的方法并不是解决这个特定问题的最佳方案,但为了解释海报的问题,它应该足够了。
稳定排序将始终在相同的输入上返回相同的解决方案(排列)。
例如,[2,1,2]将使用稳定排序作为排列[2,1,3]进行排序(首先是索引2,然后是索引1,然后是索引3在排序输出中)。这意味着输出总是以相同的方式洗牌。其他非稳定但仍然正确的排列是[2,3,1]。
快速排序不是稳定排序,同一元素之间的排列差异取决于选择枢轴的算法。一些实现是随机选择的,这可能会使快速排序在使用相同算法的相同输入时产生不同的排列。
稳定排序算法是必要的确定性。
sort([(5,3),(1,5),(3,3),(1,3)], x) => [(1,5),(1,3),(3,3),(5,3)]
。我可以制作一个始终(确定性地)输出[(1,3),(1,5),(3,3),(5,3)]
的确定性排序,但这不是一种稳定排序。 - cowbert
IBM(插入排序,冒泡排序,归并排序)
- roottraveller