1:归并排序
归并排序: 是建立在归并操作上的一种有效,稳定的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。
归并排序-归并排序:
- 时间复杂度: O ( N l o g 2 n ) O(Nlog_2^n) O(Nlog2n)
- 空间复杂度: O ( N ) O(N) O(N)
- 稳定性:稳定
递归实现:
public class 递归实现 {
public static void main(String[] args) {
int[] array = new int[]{4, 2, 6, 7, 8, 1, 22, 11, 44, 24, 13};
mergeSort(array,0,array.length-1);
System.out.println(Arrays.toString(array));
}
private static void mergeSort(int[] array,int low, int high){
//左边下标小于等于右边下标
if(low>=high){
return;
}
int mid=(low+high) >>> 1;
//递归的分解左边
mergeSort(array, low, mid);
//递归的分解右边
mergeSort(array, mid+1, high);
//合并两个归并段
merge(array,low,high,mid);
}
private static void merge(int[] array,int low, int high , int mid){
int [] temp=new int[(high-low)+1];
int k=0;
int s1=low;
int e1=mid;
int s2=mid+1;
int e2=high;
//归并,两个分段的low下标的元素比较,谁小将谁插入到temp中
while (s1<=e1 && s2<=e2){
if(array[s1]<array[s2]){
temp[k++]=array[s1++];
}else{
temp[k++]=array[s2++];
}
}
//剩余的数组元素
while (s1<=e1){
temp[k++]=array[s1++];
}
while (s2<=e2){
temp[k++]=array[s2++];
}
//将temp数组的内容复制到array
for(int i=0 ; i<temp.length ; i++){
array[i+low]=temp[i];
}
}
}
非递归实现:
package 排序.归并排序;
import java.util.Arrays;
/**
* ClassName:非递归实现
* Package:排序.归并排序
* Description:
*
* @date:2022/5/18 21:01
* @author:LiaoKe
*/
public class 非递归实现 {
public static void main(String[] args) {
int[] array = new int[]{4, 2, 6, 7, 8, 1, 22, 11, 44, 24, 13};
mergeSort(array);
System.out.println(Arrays.toString(array));
}
//从一个一个有序,一直到以整个数组长为单位有序
private static void mergeSort(int[] array ){
int gap=1;
while (gap<array.length){
for(int i=0 ; i < array.length ; i+=2*gap){
int low = i;
int mid = low + gap - 1;
//防止mid下标越界
if(mid >= array.length){
mid = array.length - 1;
}
int high = mid + gap;
//防止high下标越界
if(high >= array.length){
high = array.length - 1;
}
merge(array,low,high,mid);
}
gap = 2 * gap;
}
}
private static void merge(int [] array , int low , int high, int mid){
int k=0;
int[] temp =new int[high-low+1];
int s1=low;
int e1=mid;
int s2=mid+1;
int e2=high;
while (s1<=e1 && s2<=e2){
if(array[s1]<array[s2]){
temp[k++]=array[s1++];
}else {
temp[k++]=array[s2++];
}
}
while (s1<=e1){
temp[k++]=array[s1++];
}
while (s2<=e2){
temp[k++]=array[s2++];
}
for(int i=0 ; i < temp.length ; i++){
array[low+i]=temp[i];
}
}
}
2:排序总结
排序: 所谓排序,就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作。
稳定性: 假定在待排序的记录序列中,存在多个具有相同的关键字的记录,若经过排序,这些记录的相对次序保持不变,即在原序列中, r [ i ] = r [ j ] r[i]=r[j] r[i]=r[j],且 r [ i ] r[i] r[i]在 r [ j ] r[j] r[j]之前,而在排序后的序列中, r [ i ] r[i] r[i]仍在 r [ j ] r[j] r[j]之前,则称这种排序算法是稳定的;否则称为不稳定的。
内部排序:
数据加载到内存进行排序。
外部排序:
不在内存中排序。
基于比较的排序:
关键字进行比较排序。
非比较排序:
不进行比较的排序。
排序 | 时间复杂度 | 空间复杂度 | 稳定性 |
---|---|---|---|
直接插入排序 | 最好: O ( N ) O(N) O(N) 最坏: O ( N 2 ) O(N^2) O(N2) | O ( 1 ) O(1) O(1) | 稳定 |
希尔排序 | 和Gap增量有关 | O ( 1 ) O(1) O(1) | 不稳定 |
选择排序 | O ( N 2 ) O(N^2) O(N2) | O ( 1 ) O(1) O(1) | 不稳定 |
堆排序 | O ( N ∗ l o g 2 n ) O(N*log_2^n) O(N∗log2n) | O ( 1 ) O(1) O(1) | 不稳定 |
冒泡排序 | O ( N 2 ) O(N^2) O(N2) | O ( 1 ) O(1) O(1) | 稳定 |
快速排序 | 最好: O ( N ∗ l o g 2 n ) O(N*log_2^n) O(N∗log2n) 最坏: O ( N 2 ) O(N^2) O(N2) | 最坏: O ( N ) O(N) O(N)最好: O ( l o g 2 n ) O(log_2^n) O(log2n) | 不稳定 |
归并排序 | O ( N ∗ l o g 2 n ) O(N*log_2^n) O(N∗log2n) | O ( N ) O(N) O(N) | 稳定 |