排序算法是程序员面试过程当中经常会考的知识点,具体包括插入排序、冒泡排序、归并排序、堆排序和快速排序等,主要的考察点有额外空间的消耗,平均时间复杂度以及最坏时间复杂度。并且还有时候会考察什么时候用哪种排序算法比较合理。
一,插入排序
介绍
最简单的排序算法之一是插入排序(insert Sort),插入排序是由N-1趟排序组成。排序规则如下:
①.如果数组array的大小为0或1,则返回;
②.如果数组大于1,先比较array[1]和array[0]进行比较,如果array[0]大于array[1],交换它们的位置;
③.将array[2]依次与array[1],array[0]按照规则②进行比较;
④.后面其他数的比较按照③的规则进行。
示例:
原始数组 |
34 |
8 |
64 |
51 |
32 |
21 |
移动的位置 |
P=1 |
8 |
34 |
64 |
51 |
32 |
21 |
1 |
P=2 |
8 |
34 |
64 |
51 |
32 |
21 |
0 |
P=3 |
8 |
34 |
51 |
64 |
32 |
21 |
1 |
P=4 |
8 |
32 |
34 |
51 |
64 |
21 |
3 |
P=5 |
8 |
21 |
32 |
34 |
51 |
64 |
4 |
算法分析
最坏复杂度计算
上面表格中可以得出,最坏的情形出现在原始数组本身就是一个按从大到小的顺序排序的数组,这样每个位置的元素进行比较都会进行P次比较,所以最后的比较次数为:
1+2+...+(N-1) = O(N^2)
因此插入排序最坏时间复杂度为O(N^2)。
另一方面,如果输入数据时按照从小到大顺序排列好了的,那么就是最好的情况,也就是最好时间复杂度为O(N);
另外,插入排序的每个元素与它之前的元素进行比较的时候,每次都会进行P次比较,所以其平均复杂度为 O(N^2)。
插入排序通过把序列中的值插入一个已经排序好的序列中,直到该序列的结束。插入排序是对冒泡排序的改进。它比冒泡排序快2倍。一般不用在数据大于1000的场合下使用插入排序,或者重复排序超过200数据项的序列。
JAVA代码如下:
public static <AnyType extends Comparable<? super AnyType>> void insertSort(
AnyType[] a) {
if (a.length == 0)
return;
int j;
for (int p = 1; p < a.length; p++) {
AnyType tmp = a[p];
for (j = p; j > 0 && tmp.compareTo(a[j - 1]) < 0; j--) {
a[j - 1] = tmp;
}
a[j] = tmp;
}
}
二,冒泡排序
冒泡排序(Bubble Sort)是一种简单的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端。
冒泡排序算法的运作如下:
- 比较相邻的元素。如果第一个比第二个大,就交换他们两个。
- 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。
- 针对所有的元素重复以上的步骤,除了最后一个。
- 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较
具体代码如下:
public static <AnyType extends Comparable<? super AnyType>> void bubbleSort(
AnyType[] a) {
AnyType temp;
for(int i=0;i<a.length-1;i++){
for(int j=0;j<a.length-1-i;j++){
if(a[j].compareTo(a[j+1])>0){
temp=a[j];
a[j]=a[j+1];
a[j+1]=temp;
}
}
}
for(int i=0;i<a.length;i++)
System.out.println(a[i]);
}
三,归并排序
四,堆排序
五,快速排序