1 有序度和逆序度的介紹
有序度是指數組中具有有序關係的元素對個數。舉個糖炒栗子,
2 , 4, 3 的有序度是2,有序數對是(2,3)(2,4)。
一個完全有序的數組的有序度(即滿有序度)是 n*(n-1)/2,上面的是3。因爲有序度是2,滿有序度是3
逆有序度 = 滿有序度 - 有序度
所以逆有序度爲1 ,逆有序數對是(4,3)
// 有序
a[i]<= a[j] && i < j
// 逆序
a[i]<= a[j] && i > j
排序算法本質就是一個減少逆序度,增加有序度的過程(這裏侷限局升序)
那麼,有序度和逆序度有什麼用呢?---- 可以用來計算或者估算,排序過程中數據的交換次數。
舉個例子,一個待排序數列 2 3 1 4,滿有序度是6,它們分別是(1,2)(1,3)(1,4)(2,3)(2,4)(3,4)。該序列的有序度爲(2,3)(2,4)(1,4)(3,4),所以,逆有序度爲6-4=2。
即,經過兩次數據交換,可以讓該序列變得有序。
2 冒泡排序
思想:
n個數進行n次遍歷,每次遍歷將最大的數放到最後,然後在剩下的n-1個數中重複這樣的操作。n次後就可以得到一個有序數列。
示意圖:
public class algrithm {
public static void main(String[] args) {
int[] arr = new int[]{9,5,6,2,8,3,7,1};
print(arr);
BubbleSort(arr);
print(arr);
}
//時間複雜度 O(n^2)
//空間複雜度O(1)
public static final void BubbleSort(int[] arr){
if (arr.length == 0 ){
return;
}
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];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
}
}
4 選擇排序
思想:
每次遍歷得到一個最小的數,然後跟數列第一個位置做交換。剩下的n-1個數重複這樣的操作,n次後得到一個有序數列。
示意圖:
//時間複雜度 O(n^2)
//空間複雜度O(1)
public static final void selectSort(int[] arr){
if (arr.length < 1 ){
return;
}
for (int i = 0; i < arr.length; i++) {
int min = arr[i];
int swapNum = i;
for (int j = i; j < arr.length; j++) {
if(arr[j]<min){
min = arr[j];
swapNum = j;
}
}
int tmp = arr[i];
arr[i] = arr[swapNum];
arr[swapNum]=tmp;
}
}
5 插入排序
思想:
將一個未排序的數列第一位看成是有序的,然後將第二位插入到前面有序的數列中。以此類推,n次操作後得到一個有序數列
示意圖:
//時間複雜度 O(n^2)
//空間複雜度O(1)
public static final void insertSort(int[] arr){
if (arr.length < 1 ){
return;
}
for (int i = 1; i < arr.length; i++) {
int value = arr[i];
int j = i - 1;
for (; j >=0 ; j--) {
if (arr[j]>value){
arr[j+1] = arr[j];
}else {
break;
}
}
arr[j+1] = value;
}
}