排序算法分类
排序:将一组对象按照某种逻辑顺序重新排列的过程。
按照待排序数据的规模分为:
内部排序:数据量不大,全部存在内存中;
外部排序:数据量很大,无法一次性全部存在内存中,因此排序中需要访问外存。
按照排序是否稳定分为:
稳定排序:相等的元素在排序前后的相对位置不变。例如,a等于b,且原序列a在b前,排序后a仍在b前,则为稳定排序。
不稳定排序:相等元素在排序前后的相对位置可能发生变化。
按照是否需要额外内存分为:
原地排序:在排序过程中不申请多余的存储空间,只利用原来存储待排数据的存储空间进行比较和交换的数据排序。
非原地排序:需要额外内存空间存储数组副本以辅助排序。
按照排序方式分为:
比较类排序:通过比较来决定元素间的相对次序。
非比较类排序:不通过元素间的比较进行排序。
比较类排序
冒泡排序
冒泡排序是一种典型的交换排序。
算法原理:
比较相邻的元素。如果第一个比第二个大,就交换它们两个;
对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对。这一步结束后,排在最后的元素会是所有数据中最大的数;
针对所有的元素重复以上的步骤,除了最后一个;
持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
性能评价:
当nums[j] == nums[j+1]时,我们并不交换它们。所以冒泡排序是稳定的;
共循环了(n-1)+(n-2)+…+2+1=n(n-1)/2,所以时间复杂度是O(n^2)。
快速排序
快速排序是从冒泡排序演变而来的,实际上是在冒泡排序基础上的递归分治法。
快速排序在每一轮挑选一个基准元素,并让其他比它大的元素移动到数列一边,比它小的元素移动到数列的另一边,从而把数列拆解成了两个部分。
快排也用了分治策略,其本质框架类似二叉树的前序遍历。
时间复杂度:O(nlogn)
空间复杂度:O(1)
稳定性:不稳定
插入排序
基本思想:将待排序数据看成由已排序和未排序两部分组成。对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。
算法流程:
从第一个元素开始,该元素可以认为已经被排序;
取出下一个元素,在已经排序的元素序列中从后向前扫描;
如果该元素(已排序)大于新元素,将该元素移到下一位置;
重复步骤3,直到找到已排序的元素小于或者等于新元素的位置;
将新元素插入到该位置后;
重复步骤2~5。