这几天笔试了好几次了,连续碰到一个关于常见排序算法稳定性判别的问题,往往还是多选,对于我以及和我一样拿不准的同学可不是一个能轻易下结论的题目,当然如果你笔试之前已经记住了数据结构书上哪些是稳定的,哪些不是稳定的,做起来应该可以轻松搞定。本文是针对老是记不住这个或者想真正明白到底为什么是稳定或者不稳定的人准备的。
首先,排序算法的稳定性大家应该都知道,通俗地讲就是能保证排序前2个相等的数其在序列的前后位置顺序和排序后它们两个的前后位置顺序相同。在简单形式化一下,如果Ai = Aj, Ai原来在位置前,排序后Ai还是要在Aj位置前。
其次,说一下稳定性的好处。排序算法如果是稳定的,那么从一个键上排序,然后再从另一个键上排序,第一个键排序的结果可以为第二个键排序所用。基数排序就是这样,先按低位排序,逐次按高位排序,低位相同的元素其顺序再高位也相同时是不会改变的。另外,如果排序算法稳定,对基于比较的排序算法而言,元素交换的次数可能会少一些(个人感觉,没有证实)。
回到主题,现在分析一下常见的排序算法的稳定性,每个都给出简单的理由。
(1)冒泡排序
冒泡排序就是把小的元素往前调或者把大的元素往后调。比较是相邻的两个元素比较,交换也发生在这两个元素之间。所以,如果两个元素相等,我想你是不会再无聊地把他们俩交换一下的;如果两个相等的元素没有相邻,那么即使通过前面的两两交换把两个相邻起来,这时候也不会交换,所以相同元素的前后顺序并没有改变,所以冒泡排序是一种稳定排序算法。
(2)选择排序
选择排序是给每个位置选择当前元素最小的,比如给第一个位置选择最小的,在剩余元素里面给第二个元素选择第二小的,依次类推,直到第n-1个元素,第n个元素不用选择了,因为只剩下它一个最大的元素了。那么,在一趟选择,如果当前元素比一个元素小,而该小的元素又出现在一个和当前元素相等的元素后面,那么交换后稳定性就被破坏了。比较拗口,举个例子,序列5 8 5 2 9, 我们知道第一遍选择第1个元素5会和2交换,那么原序列中2个5的相对前后顺序就被破坏了,所以选择排序不是一个稳定的排序算法。
(3)插入排序
插入排序是在一个已经有序的小序列的基础上,一次插入一个元素。当然,刚开始这个有序的小序列只有1个元素,就是第一个元素。比较是从有序序列的末尾开始,也就是想要插入的元素和已经有序的最大者开始比起,如果比它大则直接插入在其后面,否则一直往前找直到找到它该插入的位置。如果碰见一个和插入元素相等的,那么插入元素把想插入的元素放在相等元素的后面。所以,相等元素的前后顺序没有改变,从原无序序列出去的顺序就是排好序后的顺序,所以插入排序是稳定的。
(4)快速排序
快速排序有两个方向,左边的i下标一直往右走,当a[i] <= a[center_index],其中center_index是中枢元素的数组下标,一般取为数组第0个元素。而右边的j下标一直往左走,当a[j] > a[center_index]。如果i和j都走不动了,i <= j, 交换a[i]和a[j],重复上面的过程,直到i>j。 交换a[j]和a[center_index],完成一趟快速排序。在中枢元素和a[j]交换的时候,很有可能把前面的元素的稳定性打乱,比如序列为 5 3 3 4 3 8 9 10 11, 现在中枢元素5和3(第5个元素,下标从1开始计)交换就会把元素3的稳定性打乱,所以快速排序是一个不稳定的排序算法,不稳定发生在中枢元素和a[j] 交换的时刻。
(5)归并排序
归并排序是把序列递归地分成短序列,递归出口是短序列只有1个元素(认为直接有序)或者2个序列(1次比较和交换),然后把各个有序的段序列合并成一个有序的长序列,不断合并直到原序列全部排好序。可以发现,在1个或2个元素时,1个元素不会交换,2个元素如果大小相等也没有人故意交换,这不会破坏稳定性。那么,在短的有序序列合并的过程中,稳定是是否受到破坏?没有,合并过程中我们可以保证如果两个当前元素相等时,我们把处在前面的序列的元素保存在结果序列的前面,这样就保证了稳定性。所以,归并排序也是稳定的排序算法。
(6)基数排序
基数排序是按照低位先排序,然后收集;再按照高位排序,然后再收集;依次类推,直到最高位。有时候有些属性是有优先级顺序的,先按低优先级排序,再按高优先级排序,最后的次序就是高优先级高的在前,高优先级相同的低优先级高的在前。基数排序基于分别排序,分别收集,所以其是稳定的排序算法。
(7)希尔排序(shell)
希尔排序是按照不同步长对元素进行插入排序,当刚开始元素很无序的时候,步长最大,所以插入排序的元素个数很少,速度很快;当元素基本有序了,步长很小,插入排序对于有序的序列效率很高。所以,希尔排序的时间复杂度会比o(n^2)好一些。由于多次插入排序,我们知道一次插入排序是稳定的,不会改变相同元素的相对顺序,但在不同的插入排序过程中,相同的元素可能在各自的插入排序中移动,最后其稳定性就会被打乱,所以shell排序是不稳定的。
(8)堆排序
我们知道堆的结构是节点i的孩子为2*i和2*i+1节点,大顶堆要求父节点大于等于其2个子节点,小顶堆要求父节点小于等于其2个子节点。在一个长为n 的序列,堆排序的过程是从第n/2开始和其子节点共3个值选择最大(大顶堆)或者最小(小顶堆),这3个元素之间的选择当然不会破坏稳定性。但当为n /2-1, n/2-2, ...1这些个父节点选择元素时,就会破坏稳定性。有可能第n/2个父节点交换把后面一个元素交换过去了,而第n/2-1个父节点把后面一个相同的元素没有交换,那么这2个相同的元素之间的稳定性就被破坏了。所以,堆排序不是稳定的排序算法。
综上,得出结论: 选择排序、快速排序、希尔排序、堆排序不是稳定的排序算法,而冒泡排序、插入排序、归并排序和基数排序是稳定的排序算法。
转:http://blog.chinaunix.net/uid-26495963-id-3067656.html
分享到:
相关推荐
通过对各种排序算法的性能分析和改进,我们可以更好地理解每种算法的优点和局限性,从而在实际应用中做出合理的选择,提高系统的整体性能。未来的研究可以进一步探索新的排序算法,或者在现有算法的基础上进行更深...
常见的内部排序算法包括但不限于: 1. **直接插入排序**:逐个遍历列表中的每个元素,将其插入到已排序序列的正确位置。适用于小规模数据集。 2. **冒泡排序**:重复遍历待排序序列,每次遍历时比较相邻两个元素,...
舍伍德在这个主题上进行的研究可能包括对快速排序算法的优化和性能分析。 快速排序的基本思想是选取一个基准元素,通过一趟排序将待排序的数据分割成独立的两部分,其中一部分的所有数据都比另一部分的所有数据都要...
### 二、常见排序算法描述 1. **选择排序**:选择排序从第一个元素开始,找到剩余元素中的最小值,与第一个元素交换位置,然后在剩余元素中找最小值与第二个元素交换,依此类推。这样每次都能确保当前未排序部分的...
通过对几种常见排序算法的介绍和分析,我们可以看到不同的算法各有优缺点。选择合适的排序算法不仅要看其时间复杂度和空间复杂度,还要考虑数据的具体情况和应用场景的需求。此外,不断探索和创新,开发出更适合特定...
总结来说,这个课程设计是关于理解、比较和评估内部排序算法的实践项目,旨在提升学生的算法分析能力和解决问题的能力,为未来的软件开发工作打下坚实基础。通过这样的学习,学生不仅能掌握各种排序算法,还能了解到...
在对给定文件进行知识点的提取前,需要澄清一点:文件内容中有一部分文字因为OCR扫描识别错误或遗漏,因此提取的知识点可能无法...在实际应用中,进行定量分析和比较不同排序算法的性能,是选择排序方法的重要依据。
本文旨在系统地介绍Java中常见的排序算法,并对其性能特点进行对比分析。 #### 二、排序算法分类 根据排序算法的工作原理,可将其分为以下几大类: 1. **插入排序** - 直接插入排序 - 希尔排序 2. **交换排序**...
本文将详细介绍几种常见的排序算法,并对其进行深入分析。 #### 基本概念 排序算法的目标是对一组数据进行重新排列,使其按照特定的顺序(升序或降序)排列。在评价排序算法时,我们通常会关注以下两个方面: - **...
本实验报告主要探讨了数据结构中的几种常见排序算法的实现与性能比较。排序是计算机科学中最基础且重要的操作之一,它在各种领域都有广泛的应用,如数据库、数据分析等。实验的目标是加深对排序算法的理解,通过编程...
《武汉理工数据结构排序算法比较实验报告》是对各种内部排序算法进行分析和比较的实践性研究。该实验涉及了多种常见的排序算法,如冒泡排序、直接插入排序、简单选择排序、快速排序、希尔排序以及归并排序。通过在PC...
本项目中,李伟民同学通过Java语言实现了五种常见的排序算法:插入排序、冒泡排序、堆排序、合并排序和快速排序,并对它们的性能进行了分析和比较。以下是这五种排序算法的基本思想和实现方法的详细说明: 1. **...
基数排序作为经典的排序算法之一,因其稳定性和对特定数据集的高效性,在某些场景下是理想的选择。然而,它也存在空间需求大和不适用于非整数类型的问题,因此在选择排序算法时需要根据实际需求权衡。在理解和掌握...
3. **稳定性**:一个排序算法的稳定性是指它在排序过程中是否保持相同值元素的相对顺序不变。稳定的排序算法对于处理含有重复数据的情况尤为重要。 4. **适应性**:算法对输入数据的特性做出反应的能力。例如,插入...
通过对这四种排序算法的理论描述、性能分析和实际测试,我们可以得出如下结论:快速排序在多数情况下表现出最优的性能,是这四种算法中最快的排序方法。归并排序保持稳定的O(nlogn)复杂度,适用于数据量大且对稳定性...
冒泡排序和快速排序是两种常见的排序算法,它们在排序过程中的时间性能有很大的差异。在本文中,我们将比较冒泡排序和快速排序的时间性能,并讨论它们在实际应用中的优缺点。 冒泡排序的时间性能: 冒泡排序的时间...
根据数据是否全部加载到内存中,排序算法可以分为内部排序和外部排序两大类。内部排序是指数据完全存放在内存中进行的排序过程,而外部排序则是针对无法一次性装载入内存的大规模数据集。本文重点讨论内部排序算法的...
- **8.2-3** 分析计数排序算法的稳定性。 - **8.2-4** 比较计数排序与其他线性时间排序算法的性能。 #### 8.3 基数排序 - **8.3-1** 提供一个具体的基数排序实现代码。 - **8.3-2** 探讨基数排序的时间复杂度。 - *...