比较三种排序方法
排序方法 | 时间复杂度 | 最佳情况 | 额外空间复杂度 | 是否稳定 |
---|---|---|---|---|
选择排序(Selection Sort) | 否 | |||
冒泡排序(Bubble Sort) | 是 | |||
插入排序(Insertion Sort) | 是 |
一、选择排序
基本方法: 每次循环都找出剩余数列元素中最小的值并与剩余数列的首位交换。
即在第一次循环时找出整个数列中最小的值并与数列中第一位交换。
第二次循环时找出从第二位到最后一位中最小的元素,并与第二位进行交换。
如此继续直至第n次循环。这样的话,时间复杂度为
,但排序是不稳定的,即原有值相同的两个元素的先后顺序会改变。
例如: 对列表( 3, 2, 1, 5, 4 )进行排序
排好序的左子列表 | 未排好序的右子列表 | 最小元素 |
---|---|---|
( ) | ( 3, 2, 1, 5, 4 ) | 1 |
( 1 ) | ( 3, 2, 5, 4 ) | 2 |
( 1, 2 ) | ( 3, 5, 4 ) | 3 |
( 1, 2, 3 ) | ( 5, 4 ) | 4 |
( 1, 2, 3, 4 ) | ( 5 ) | 5 |
( 1, 2, 3, 4, 5 ) | ( ) |
以下为选择排序的Java代码实现:
public static void selectionSort(int[] arr){
for (int i = 0; i < arr.length; i++){
int minI = i;
for (int j = i; j < arr.length; j++){
if (arr[j] < arr[minI]){
minI = j;
}
}
int temp = arr[i];
arr[i] = arr[minI];
arr[minI] = temp;
}
}
二、冒泡排序
基本方法: 依次比较相邻的两个数,将较大的数放在后面。
即在第一次循环时首先比较第1个与第2个数,如第一个数比第二个数大,则交换这两个数,否则不交换。再比较第2个与第3个数,同样地,如第2个数比第3个数大,则交换。如此继续,直到比较完最后一个数和倒数第二个数并交换后,数列中最大的数会在最后一位上。
同样地,第二趟完成后数列中倒数二大的数会在倒数第二位。
如此继续直至第n次循环。这样的话,时间复杂度为
,且排序是稳定的,即原有值相同的两个元素的先后顺序会保持不变。
可以对此进行优化,如果某一趟并没有发生交换,则判定数列已经排好序,提前结束。这样的话,如果数列已经排好序的话,则只需循环一次。
例如: 对列表( 3, 2, 1, 5, 4 )进行排序
第一次循环:
( 3, 2, 1, 5, 4 ),3>2,所以交换3和2
( 2, 3, 1, 5, 4 ),3>1,所以交换3和1
( 2, 1, 3, 5, 4 ),3<5,不做交换
( 2, 1, 3, 5, 4 ),5>4,所以交换5和4
( 2, 1, 3, 4, 5 )
第二次循环:
( 2, 1, 3, 4, 5 ),2>1,所以交换2和1
( 1, 2, 3, 4, 5 ),2<3,不做交换
( 1, 2, 3, 4, 5 ),3<5,不做交换
( 1, 2, 3, 4, 5 ),4<5,不做交换
( 1, 2, 3, 4, 5 )
第三次循环:
( 1, 2, 3, 4, 5 ),1>2,不做交换
( 1, 2, 3, 4, 5 ),2<3,不做交换
( 1, 2, 3, 4, 5 ),3<5,不做交换
( 1, 2, 3, 4, 5 ),4<5,不做交换
( 1, 2, 3, 4, 5 )
因为本次循环没有交换,提前跳出循环
以下为冒泡排序的Java代码实现:
public static void bubbleSort(int[] arr){
boolean isSorted = true;
for (int i = 0; i < arr.length; i++){
for (int j = 0; j < arr.length - i - 1; j++){
if (arr[j] > arr[j+1]){
int temp = arr[j+1];
arr[j+1] = arr[j];
arr[j] = temp;
isSorted = false;
}
}
if (isSorted) {
break;
}
}
}
三、插入排序
基本方法: 将列表分为两个部分,已排序部分和未排序部分,每次循环依次将元素从未排序部分插入已排序部分使之保持有序
第一次循环,将第一个元素插入已排序部分,即列表保持不变
第二次循环,将第二个元素插入含有一个元素的已排序部分
继续如此,直至第n次循环。时间复杂度为
,且排序是稳定的,即原有值相同的两个元素的先后顺序会保持不变。
例如: 对列表( 3, 2, 1, 5, 4 )进行排序
排好序的左子列表 | 未排好序的右子列表 |
---|---|
( ) | ( 3, 2, 1, 4, 5 ) |
( 3 ) | ( 2, 1, 4, 5 ) |
( 2, 3 ) | ( 1, 4, 5 ) |
( 1, 2, 3 ) | ( 4, 5 ) |
( 1, 2, 3, 4 ) | ( 5 ) |
( 1, 2, 3, 4, 5 ) | ( ) |
以下为插入排序的Java代码实现:
public static void insertionSort(int[] arr){
for (int i = 0; i < arr.length; i++){
int temp = arr[i];
int j = i - 1;
for (; j >= 0; j--){
if (arr[j] > temp){
arr[j+1] = arr[j];
}
else {
break;
}
}
arr[j+1] = temp;
}
}