4. 希尔排序
- 时间复杂度 : O(n^1.3) ~ O(n^1.5)
- 空间复杂度 : O(1)
- 稳定性 : 不稳定(因为在交换的过程中,有跳跃交换,所以不稳定)
- 算法思想 :希尔排序是插入排序的优化版本,由于简单插入排序的只能交换相邻元素,所以每次只能将逆序对数减1,
它通过交换不相邻的元素, 使得每次将逆序对数量减小大于1.
首先将数组元素按照h=4间距分为数对,然后在这些数对之间进行一次插入排序,然后h/2为间距进行插入排序,最后h=1,也就是相邻之间元素进行插入排序;
public static <T extends Comparable<T>> void shellSort(T[] arr) {
int n = arr.length;
int h = 1 ;
while(h <n/3 ){
h = h *3 +1 ;
}
while(h >= 1){
for(int i=h;i<n;i++){
for(int j = i ; j>h&&arr[j].compareTo(arr[j-h]);j-=h)
{
swap(arr,j,j-h);
}
}
h = h/3;
}
}
5. 归并排序
- 时间复杂度 : O(nlogn) 划分过程类似二分(logn) 归并过程需要将数组都遍历一遍(O(n))
- 空间复杂度: 使用了辅助数组> O(n)
- 稳定性: 稳定
- 算法思想 : 基于分治的思想,首先先将数组不断划分,划分规模至两个相邻元素,然后进行归并,合并两个有序数组,刚开始是相邻元素之间合并,再往后,规模不断扩大,实现全数组的合并
public class 归并排序 {
public static void mergeSort(int[] arr, int low, int high, int[] temp) {
if (low < high) {
int mid = (low + high) / 2;
mergeSort(arr, low, mid, temp);
mergeSort(arr, mid + 1, high, temp);
merge(arr, low, mid, high, temp);
}
}
private static void merge(int[] arr, int low, int mid, int high, int[] temp) {
int i = 0;
int j = low;
int k = mid + 1;
while (j <= mid && k <= high) {
if (arr[j] < arr[k]) {
temp[i++] = arr[j++];
} else {
temp[i++] = arr[k++];
}
}
while (j <= mid) {
temp[i++] = arr[j++];
}
while (k <= high) {
temp[i++] = arr[k++];
}
for (int n = 0; n < i; n++) {
arr[low + n] = temp[n];
}
}
public static void main(String[] args) {
int[] arr = {11, 44, 23, 67, 88, 65, 34, 48, 9, 12};
int[] tmp = new int[arr.length];
mergeSort(arr, 0, arr.length - 1, tmp);
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
}
}
6. 快速排序
- 时间复杂度 : 加入每4次正好将数组对半分,这种情况下递归调用次数才是最小的,最好情况为 : O(nlogn),而如果每次切分第一次从最小的元素切分,第二次从第二小元素切分,此时最坏情况: O(n^2)
- 空间复杂度: 因为没有开辟辅助数组 O(1)
- 算法思想 : 基于分治的思想,将数组不 断的向小规模划分,每次向小规模划分的过程中会有一个partition的过程,在这个过程中会取第一个元素为切分元素,不断的从两头向中间遍历,从头遍历时如果遇到比自己小的元素,就将它放到切分元素的位置,从后往前遍历时,如果遇到比自己小的元素,就将其方放到从前往后遍历的最小元素的位置,每次partition,都能将数组中的元素根据切分元素分离开来,小于切分元素的在数组的前面,大于切分元素的在数组的后面.
public static void QuickSort(int[] arr, int l, int h) {
if (h <= l) {
return;
}
int m = partition(arr, l, h);
QuickSort(arr, l, m-1);
QuickSort(arr, m + 1, h);
}
private static int partition(int[] arr, int l, int h) {
int i = l;
int j = h + 1;
int v = arr[l];
while (true) {
while (v > arr[i++] && i != h) {
}
while (v < arr[--j] && j != l) {
}
if (i >= j)
break;
swap(arr, i, j);
}
swap(arr,l,j);
return j;
}
private static void swap(int[] arr, int i, int j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}