1.冒泡排序
- 思想:在一趟中找到最大值,放到末尾,接着走一趟寻找最大值,放到倒数第二位,循环一直到最后一位。
- 改进:如果已经排好序,就不需要继续循环了。
public class Solution {
// 如果中间已经排好
public int[] bubble_sort(int[] arr) {
if (arr.length == 0 || arr == null) return null;
int count = 0;
for (int i = arr.length-1; i > 0; i-- ) {
// 如果最优的话只需要在这里走一趟
for (int j = 0; j < i; j++) {
if (arr[j] > arr[j+1]) {
count = 1;
swap(arr, j, j+1);
}
}
if (count == 0) break;
}
return arr;
}
public void swap(int[] arr, int i, int j) {
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
public static void main(String[] args) {
Solution so = new Solution();
int[] arr = {5, 4, 3, 2, 1};
int[] newArr = so.bubble_sort(arr);
if (newArr == null) return;
for (int t : newArr) {
System.out.print(t + " ");
}
}
}
时间复杂度最优O(n),只需要走一趟,最坏是O(n^2),因为数组是逆序的
它是稳定的,因为遇到相等的数,不改变顺序
用冒泡排序处理单向链表,这种需要交换元素的,是没问题的。
2.插入排序
- 思想:当插入一个新的元素时,比较大小,如果否合条件,一个个的往后错
public class Solution {
// 如果中间已经排好
public int[] insert_sort(int[] arr) {
if (arr.length == 0 || arr == null) return null;
int i = 1, j = 1;
for (i = 1; i < arr.length; ++i) {
int tmp = arr[i];
// 是插入元素和每个之前的元素比大小
// 符合要求的就往后移一位
// 不符合要求就停止
for (j = i; j > 0 && arr[j - 1] > tmp; --j) {
// 不符合要求是 arr[j-1] <= tmp
arr[j] = arr[j - 1];
}
arr[j] = tmp;
}
return arr;
}
public static void main(String[] args) {
Solution so = new Solution();
int[] arr = {5, 4, 3, 2, 1};
int[] newArr = so.insert_sort(arr);
if (newArr == null) return;
for (int t : newArr) {
System.out.print(t + " ");
}
}
}
时间复杂度最优O(n),只需要走一趟,最坏是O(n^2),因为数组是逆序的
排序算法是稳定的
插入排序不能处理单向链表,其他和冒泡排序差不多。
3、希尔排序
- 思想:利用一个增量序列,根据设定的间隔远距离交换两个元素,内部使用的是插入排序
public class Solution {
// 如果中间已经排好
public int[] shell_sort(int[] arr) {
if (arr.length == 0 || arr == null) return null;
int len = arr.length;
int i = len / 2, j = len / 2;
for (int k = len / 2; k >=1 ; k /= 2) {
// 这里是间隔元素来比
for (i = k; i < arr.length; ++i) {
int tmp = arr[i];
// j >= k, 最后一个元素也是需要计算的
for (j = i; j >= k && arr[j - k] > tmp; j -= k) {
// 不符合要求是 arr[j-1] <= tmp
arr[j] = arr[j - k];
}
arr[j] = tmp;
}
}
return arr;
}
public static void main(String[] args) {
Solution so = new Solution();
int[] arr = {81, 94, 11, 96, 12, 35, 17, 95, 28, 58, 41, 75, 15};
int[] newArr = so.shell_sort(arr);
if (newArr == null) return;
for (int t : newArr) {
System.out.print(t + " ");
}
}
}
== 时间复杂度为O(nlogn+n^2),所以时间复杂度为 O(n^2)==
- 如果增量序列不互质,那么希尔排序就不起作用
- 由于多次插入排序,我们知道一次插入排序是稳定的,不会改变相同元素的相对顺序,但在不同的插入排序过程中,相同的元素可能在各自的插入排序中移动,最后其稳定性就会被打乱,所以shell排序是不稳定的