算法和数据结构的复习不写博客是不行的,之前的Algorithm项目也是进展缓慢,于是乎,我又来写博客了。准备从排序开始,把算法导论的一些算法实现下。顺便各种数据结构也要涉及下。
排序算法分类
- 比较排序。包括插入,选择,交换,归并排序等。各元素次序基于输入元素间的比较,根据决策树模型,任何比较排序在最坏情况下都要用Ω(nlgn)次比较来进行排序。
- 非比较排序,包括基数排序等。
类别 | 排序法 | 最差时间复杂度 | 平均时间复杂度 | 空间复杂度 |
---|---|---|---|---|
1.插入排序 | 直接插入排序 | O(n^2) | O(n^2) | O(1) |
希尔排序 | O(n^1.3) | O(n^2) | O(1) | |
2.选择排序 | 直接选择排序 | O(n^2) | O(n^2) | O(1) |
堆排序 | O(nlgn) | O(nlgn) | O(1) | |
3.交换排序 | 冒泡排序 | O(n^2) | O(n^2) | O(1) |
快速排序 | O(n^2) | O(nlgn) | O(lgn)~O(n) | |
4.归并排序 | 归并排序 | O(nlgn) | O(nlgn) | O(n) 非原地归并 |
5.基数排序 | 基数排序 | O(d(r+n)) | O(d(r+n))) | O(rd+n) |
插入排序
- 基本思想:从第一个数开始,构建有序序列。对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。
- 时间复杂度:O(n^2)
- 空间复杂度:O(1)
- 特点:插入排序是一个对少量元素进行排序的有效算法。
1 | public class InsertionSort { |
带二分查找的插入排序
- 基本思想:就是在插入排序中运用二分查找的方法来节约时间。在有序数组中寻找插入的位置的时候不是从后往前一个个找,而是二分查找。
- 时间复杂度:O(nlogn)
- 空间复杂度:O(n^2)
- 特点:插入排序是一个对少量元素进行排序的有效算法。
1 | public class InsertionSort_BinarySearchEdition { |
直接选择排序
- 基本思想:
每一趟从待排序的数据元素中选出最小的一个元素,顺序放在已排好序的数列的最后,直到全部待排序的数据元素排完。 - 时间复杂度:O(n^2)
- 空间复杂度:O(1)
1 | public class SelectSort{ |
堆排序
- 基本思想:
- 首先将数组构造成一个最大堆。
- 因为A[0]为最大的,所以交换A[0]和A[n],从而达到正确的位置。
- 最后,从堆中去掉节点n(通过减小heapSize),再将A[0…n-1]建成最大堆。
- 时间复杂度:O(n^2)
- 空间复杂度:O(1)
1 | public class HeapSort { |
冒泡排序
- 算法名称:冒泡排序
- 基本思想:
- 比较相邻的元素。如果第一个比第二个大,就交换他们两个。
- 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。
- 针对所有的元素重复以上的步骤,除了最后一个。
- 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
- 时间复杂度:O(n^2)
- 空间复杂度:O(1)
1 | public class BubbleSort { |
归并排序
- 基本思想:
采用分治法,将数组分成两部分,两边分别排序,然后把排好序的两个数组合并。 - 时间复杂度:O(nlogn)
- 空间复杂度:O(n)
1 | public class MergeSort { |
快速排序
- 基本思想:
- 通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小.
- 再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列.
- 时间复杂度:下界为O(nlogn),最坏情况为O(n^2),平均时间复杂度为O(nlogn)
- 空间复杂度:在对序列的操作过程中只需花费常数级的空间,即S(1),而在递归栈上需要花费最少logn最多n的空间
先上算法导论的图例:
上图的伪代码如下:
1 | QUICKSORT(A,p,r) |
由于这个比较复杂,所以用python先做个简单的。
1 | def qsort(L): |
然后是Java版的快排。
1 | public class QuikSort { |