稳定性: 两个相等的数据,如果经过排序后,排序算法能保证其相对位置不发生变化,则我们称该算法是具备稳定性的排序算法。
-
例:2 3(a) 1 4 3(b) 经过排序后为
-
结果为: 1 2 3(a) 3(b) 4 稳定排序
-
结果为: 1 2 3(b) 3(a) 4 不稳定排序
如果一个排序是 稳定的的排序 ,那么他就 可以变为 不稳定的排序但如果一个排序本身是 不稳定排序,你 不可能 把它变为 稳定排序。
稳定排序中一般没有跳跃式交换。
常用的 七个 基于比较的 排序
-
插入排序
-
希尔排序
-
选择排序
-
堆排序
-
冒泡排序
-
快速排序(重要)
-
归并排序(重要)
直接插入排序
时间复杂度:
最坏情况:O(n^2) 最好情况(有序的情况):O(n)
非常重要:越有序越快
空间复杂度: O(1)
稳定性:稳定排序
public static void insertSort(int[] array) {
for (int i = 1; i < array.length; i++) {
int t = array[i];
int j = i-1;
for (; j >= 0 ; j--) {
if (array[j] > t) {
array[j+1] = array[j];
}else {
array[j+1] = t;
break;
}
}
array[j+1] = t;
}
}
希尔排序
采用分组的思想,组内进行直接插入排序
时间复杂度:
最坏情况:O(n^2)
最好情况:O(n)
平均:O(n^1.3)
空间复杂度: O(1)
不稳定排序
public static void shellSort(int[] array) {
int[] drr = {5,3,1};
for (int i:drr) {
shell(array,i);
}
}
public static void shell(int[] array, int gap) {
for (int i = gap; i < array.length; i++) {
int t = array[i];
int j = i - gap;
for (; j >= 0 ; j -= gap) {
if (array[j] > t) {
array[j+gap] = array[j];
}else {
array[j+gap] = t;
break;
}
}
array[j+gap] = t;
}
}
选择排序
时间复杂度: O(n^2)
空间复杂度:O(1)
不稳定排序
public static void selectSort(int[] array) {
for (int i = 0; i < array.length-1; i++) {
for (int j = i+1; j < array.length; j++) {
if (array[i] > array[j]) {
int t = array[i];
array[i] = array[j];
array[j] = t;
}
}
}
}
堆排序
时间复杂度: O(n*log(2)n)
空间复杂度: O(1)
不稳定排序
public static void adjustDown(int[] array, int root, int end) {
int p = root;
int c = p*2 + 1;
while(c < end) {
if (c+1<end && array[c]<array[c+1]) {
c++;
}
if (array[c] > array[p]) {
int t = array[c];
array[c] = array[p];
array[p] = t;
p = c;
c = 2*p+1;
}else {
break;
}
}
}
public static void createHeap(int[] array) {
for (int i = (array.length-1-1)/2; i >= 0; i--) {
adjustDown(array,i,array.length);
}
}
public static void heapSort(int[] array) {
createHeap(array);
int end = array.length;
while (end > 0) {
int t = array[0];
array[0] = array[end-1];
array[end-1] = t;
adjustDown(array,0,end-1);
end--;
}
}
冒泡排序
时间复杂度: O(n^2)
空间复杂度: O(1)
稳定性排序
public static void bubbleSort(int[] array) {
for (int i = 0; i < array.length-1; i++) {
boolean flg = false;
for (int j = 0; j < array.length-1-i; j++) {
if (array[j] > array[j+1]) {
int t = array[j];
array[j] = array[j+1];
array[j+1] = t;
flg = true;
}
}
if (flg == false) {
return;
}
}
}
快速排序(未优化)(递归)
时间复杂度: O(n*log(2)n) 最坏情况: O(n^2)
空间复杂度: O(log(2)n) 最坏情况: O(n)
不稳定排序
public static int partition(int[] array,int low,int high) {
int t = array[low];
while (high > low) {
while (array[high] >= t && high > low) {
high--;
}
array[low] = array[high];
while (array[low] <= t && high > low) {
low++;
}
array[high] = array[low];
}
array[high] = t;
return high;
}
public static void quick(int[] array, int left,int right) {
if (left >= right) {
return;
}
int par = partition(array,left,right);
quick(array,left,par-1);
quick(array,par+1,right);
}
public static void quickSort(int[] array) {
quick(array,0,array.length-1);
}
归并排序 (递归实现)
时间复杂度: n*log(2)n
空间复杂度: O(n)
稳定排序
public static void mergeSort(int[] array) {
mergeSortInternal(array,0,array.length-1);
}
public static void mergeSortInternal(int[] array, int low, int high) {
if (low >= high) {
return;
}
//分解
int mid = (low + high)>>>1;
mergeSortInternal(array, low, mid);
mergeSortInternal(array, mid+1, high);
//合并
merge(array,low, mid, high);
}
public static void merge (int[] array, int low, int mid, int high) {
int s1 = low;
int s2 = mid+1;
int len = high-low+1;
int[] ret = new int[len];
int i = 0;//用来表示ret数组的下标
//对应位置比较
while (s1 <= mid && s2 <= high) {
if (array[s1] <= array[s2]) {
ret[i++] = array[s1++];
}else {
ret[i++] = array[s2++];
}
}
//判断谁没走完,把剩下的数放到ret数组中
while (s1 <= mid) {
ret[i++] = array[s1++];
}
while (s2 <= high) {
ret[i++] = array[s2++];
}
//将ret数组中的数放到array数组中
for (int j = 0; j < ret.length; j++) {
array[j+low] = ret[j];
}
}
非基于比较的排序
- 计数排序
- 基数排序
- 桶排序
这里只说基数排序
//获得最大数
public static int getMaxValue(int[] array) {
int maxValue = array[0];
for(int value : array) {
if (maxValue < value) {
maxValue = value;
}
}
return maxValue;
}
//获得最大数位数
public static int getMaxLenght(int[] array) {
int maxValue = getMaxValue(array);
if (maxValue == 0) {
return 1;
}
int maxLenght = 0;
for (int i = maxValue; i != 0 ; i/=10) {
maxLenght++;
}
return maxLenght;
}
//扩容并存入数据
public static int[] arrayExpand(int[] array, int k) {
array = Arrays.copyOf(array, array.length+1);
array[array.length-1] = k;
return array;
}
//基数排序
public static void radixSort(int[] array) {
if (array.length == 0) {
System.out.println("数组为空");
return;
}
int maxLenght = getMaxLenght(array);
int a = 10;
int b = 1;
for (int i = 0; i < maxLenght; i++) {
int[][] ret = new int[10][0];
for (int j = 0; j < array.length; j++) {
int k = array[j]%a/b;
ret[k] = arrayExpand(ret[k], array[j]);
}
int p = 0;
for (int[] arr :ret) {
for (int n :arr) {
array[p++] = n;
}
}
a *= 10;
b *= 10;
}
}