交换排序:根据序列中两个关键字的比较结果来对换两个记录在序列中的位置。基于交换的排序有很多,本篇章主要介绍冒泡排序和快速排序。
一.冒泡排序 :从后往前两两比较相邻元素的值,若为逆序,则交换他们,(若检查两个元素值相同,为了保持稳定并不会去交换它们,此时会继续往前扫描)直到序列比较完。称这样过程为“一趟” 冒泡排序,若有n个元素,且原序列无序,总共需要n-1趟处理,每趟处理确定一个元素的位置。
注:1.第一趟排序使关键字最小的一个元素冒到最前面。
2.若某一趟没有发生交换,说明此时序列已经有序。
3.若原序列有序,则一趟就可完成排序。
4.冒泡排序也适用于链表,可以从前往后冒泡,将更大的元素冒到队尾。
算法性能分析:
最好情况(最好时间复杂度):处理前原序列已经有序,此时比较次数=n-1,交换次数=0;时间复杂度为O(n)。
最坏情况下(最坏时间复杂度):原序列逆序,此时比较次数为:
(n-1)+(n-2)+(n-3)+....+1=n(n-1)/2=交换次数,最坏时间复杂度为O(n^2)。
平均时间复杂度:O(n^2)。
稳定性:稳定。
二.快速排序(重点):在待排序表中任取一个元素作为枢轴(或基准,通常取首元素),通过一趟排序将待排序表划分为两个独立的部分,其中基准左边元素都小于基准元素,基准右边元素都大于或等于基准元素,这个过程也称为一次划分。然后递归的对两个子表重复上述过程,直至每部分内只有一个元素或空为止,即所有元素放在了其最终位置上。
注:基于算法思想可以自己尝试写出伪代码,算法实现代码十分重要,理解递归栈过程。(后期我也可能会更新这部份代码)。
算法效率分析:每一层的QuickSort只需处理剩余的待排元素,时间复杂度不超过O(n),由于一层需要一次递归,那么整体的时间复杂度=O(n*递归层数)。
注意(重点):可以把排序中的n个元素组织成二叉树,二叉树的高度就是递归调用的层数,那么n个节点的二叉树最小高度=log2n向下取整+1,最大高度=n。
时间复杂度:时间复杂度=O(n*递归层数),根据上述可知最好时间复杂度O(nlog2n)最坏时间复杂度为O(n^2)。
空间复杂度:空间复杂度=O(递归层数),最好空间复杂度=O(log2n),最坏空间复杂度=O(n)。
.
注:1.若初始序列选中的枢轴(基准)将待排序序列划分为很不均匀的两个部分,则会导致递归深度增加,算法效率变低。
2.若初始序列有序或者逆序,则快速排序的性能最差。
3.若初始序列选中的枢轴(基准)将待排序序列划分为均匀的两个部分,则递归深度最小,算法效率最高。
快速排序算法优化思路:尽量选择可以把数据中分的枢轴。
快速排序是所有内部排序算法中平均性能最优的算法。
稳定性:不稳定。