- 线性结构中排序才有意义——基于数组的排序、就地排序
- 排序算法的性能:
(1)时间复杂度:最好、最坏、平均
(2)空间复杂度:最好、最坏、平均
(3)稳定性:经过排序算法处理后,相同元素的相对位置不变,即具备稳定性
- 区间表示法:起始位置 from,终止位置 to
(1)左闭右闭 size = to - from + 1
(2)左闭右开 size = to - from
- 测试的完备性问题——针对于排序
(1)正常情况:乱序且元素个数不为0 例[9,1,3,5,2,4,0,7]
(2)特殊情况——边界法
数组中一个元素都没有 例[]
数组中的所有元素都相等 例[1,1,1,1,1]
数组已经有序 例[1,2,3,4,5]
数组是逆序 例[5,4,3,2,1]
数组中的元素很大的情况
1. 冒泡排序:减治算法
减:每次解决一个问题之后,问题规模减少
治:采用相同的方式处理相同的问题
外层循环:控制冒泡次数
内层循环:控制一趟冒泡排序中的比较次数
有序区间:[n - i, n)
无序区间:[0, n - i)
public static void bubbleSort(long[] array){
//外层循环:冒泡次数
// 当元素个数为 1 时,不需要冒泡
for(int i = 0; i < array.length - 1; i++){
boolean sorted = true;
//内层循环:需要比较的次数
// 每次比较完,将大的数放置在后面
for(int j = 0; j < array.length - i - 1; j++){
if(array[j] > array[j + 1]){
sorted = false;
swap(array, j, j + 1);
}
}
if(sorted){
return;
}
}
}
public static void swap(long[] array, int a, int b){
long t = array[a];
array[a] = array[b];
array[b] = t;
}
时间复杂度:
最好情况:O(n)——数组已有序
最坏/平均:O(n^2)——最坏:数组逆序
空间复杂度:O(1)
稳定性:具备
2. 插入排序:减治算法
外层循环: 一共要取多少个元素进行插入过程(无序区间里有多少个元素)
有序区间: [0, i]
无序区间: [i + 1, n)
内层循环:不符合元素的后移次数
public static void insetSort(long[] array){
//外层循环:需要进行插入过程的元素个数,即 array.length - 1
// 视数组中的第一个元素为有序的
for (int i = 0; i < array.length - 1; i++){
//有序区间:[0, i] 即 i == 0时至少有一个元素
//无序区间:[i + 1, n]
long k = array[i + 1]; //取出无需区间的第一个数
//从后往前遍历有序区间
int j;
for(j = i; j >= 0 && k < array[j]; j--){
array[j + 1] = array[j]; //将不符合的后退一个元素位置
}
array[j + 1] = k; //将无序区间的数放置在第一次 >= array[j]的位置
}
}
复杂度:
时间复杂度:
最好:O(n)
最坏/平均:O(n^2)
空间复杂度:O(1)
稳定性:具备—— k < array[j]
不具备—— k <= array[j]
3. 希尔排序——有间隔的插入排序
逻辑上,把数据按照固定长度的间隔做分组,各自在各自的分组内部做插入排序