一、十大排序算法

- 冒泡、选择、插入、归并、快速、希尔、堆排序,属于比较排序(Comparison Sorting)
二、冒泡排序(Bubble Sort)
- 冒泡排序也叫做起泡排序
- 执行流程
①、从头开始比较每一对相邻元素,如果第一个比第二个大,就交换它们的位置。
执行完一轮后,最末尾那个元素就是最大的元素。
②、忽略①中曾经找到的最大元素,重复执行步骤①、直到全部元素有序。

import java.util.Arrays;
public class Main {
public static void main(String[] args) {
int[] array = {10,9,19,28,37,56,34};
for (int end = array.length-1; 0 < end; end--) {
for (int begin = 1; begin <= end; begin++) {
if (array[begin] < array[begin - 1]){
int tmp = array[begin];
array[begin] = array[begin-1];
array[begin-1] = tmp;
}
}
}
System.out.println(Arrays.toString(array));
}
}
(1)冒泡排序 — 优化①
- 如果序列已经完全有序,可以提前终止冒泡排序。但是如果序列不是有序的,那么耗费的时间比上面还要多。

- 设置一个标志
boolean sorted = true;
如果sorted = true
指的是序列是有序的,没有进行数值交换的for循环(内嵌的for循环),这样最外层的循环不用执行,提高效率。
import java.util.Arrays;
public class Main {
public static void main(String[] args) {
int[] array = {10,9,19,28,37,56,34};
for (int end = array.length-1; 0 < end; end--) {
boolean sorted = true;
for (int begin = 1; begin <= end; begin++) {
if (array[begin] < array[begin - 1]){
int tmp = array[begin];
array[begin] = array[begin-1];
array[begin-1] = tmp;
sorted = false;
}
}
if (sorted) break;
}
System.out.println(Arrays.toString(array));
}
}
(2)冒泡排序 — 优化②
- 如果序列尾部已经局部有序,可以记录最后1次交换的位置,减少比较次数

对于上面的数据来说,最后面的几项数据都是有序的,并且还比前面的数据都大。那么我们只需要对前面杂乱的数据进行排序即可。
static void bubbleSort3(Integer[] array){
for (int end = array.length-1; 0 < end; end--) {
int sortedIndex = 1;
for (int begin = 1; begin <= end; begin++) {
if (array[begin] < array[begin - 1]){
int tmp = array[begin];
array[begin] = array[begin-1];
array[begin-1] = tmp;
sortedIndex = begin;
}
}
end = sortedIndex;
}
}
- 最坏、平均时间复杂度:O(n2)
- 最好时间复杂度:O(n)
- 空间复杂度:O(1)
三、排序算法的稳定性(Stability)
- 如果相等的2个元素,在排序前后的相对位置保持不变,那么这是稳定的排序算法
- 排序前:5,1, 3𝑎,4, 7, 3𝑏
- 稳定的排序: 1,3𝑎, 3𝑏, 4, 5, 7
- 不稳定的排序:1,3𝑏, 3𝑎, 4, 5,7
对自定义对象进行排序时,稳定性会影响最终的排序效果
- 冒泡排序属于稳定的排序算法
- 稍有不慎,稳定的排序算法也能被写成不稳定的排序算法,比如下面的冒泡排序代码是不稳定的

四、原地算法(In-place Algorithm)
- 原地算法:
①、不依赖额外的资源或者依赖少数的额外的资源,仅依靠输出覆盖输入。
②、空间复杂度为O(1)的都可以认为是原地算法。 - 非原地算法,称为Not-in-place或者Out-of-place
- 冒泡排序属于In-place
五、选择排序(Selection Sort)
- (1)执行流程:
①、从系列中找出最小的那个元素,然后与最前面的元素交换位置。
执行完一轮后,最前面的那个元素就是最小的元素
②、忽略①中曾经找到的最小元素,重复执行步骤①

static void selectionSort1(Integer[] array){
for (int i = 0; i < array.length - 1; i++) {
int min = i;
for (int j = i + 1; j < array.length; j++) {
if (array[j] < array[min]) {
min = j;
}
}
if (i != min) {
int tmp = array[i];
array[i] = array[min];
array[min] = tmp;
}
}
}
- (2)执行流程:
①、从系列中找出最大的那个元素,然后与最末尾的元素交换位置。
执行完一轮后,最末尾的那个元素就是最大的元素
②、忽略①中曾经找到的最大元素,重复执行步骤①
static void selectionSort2(Integer[] array){
for (int end = array.length-1; end > 0; end--) {
int maxIndex = 0;
for (int begin = 1; begin <= end; begin++) {
if (array[maxIndex] <= array[begin]){
maxIndex = begin;
}
}
int tmp = array[maxIndex];
array[maxIndex] = array[end];
array[end] = tmp;
}
}
- 选择排序的交换次数要远远少于冒泡排序,平均性能优于冒泡排序
- 最好、最坏、平均时间复杂度:O(n2),空间复杂度:O(1),属于不稳定排序