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;
}
}