https://mp.csdn.net/console/editor/html/108763772 这篇文章实现了插入排序
插入排序相对比较简单也好理解,但是插入排序的时间复杂是很高的 O(n^2)
所以需要对插入排序进行优化,这里我们使用归并排序来进行优化
归并排序
通过二分的思想将数组元素拆分到只剩一个为止,在对我们的元素进行合并处理,合并的时候需要比较数组中的元素大小
时间复杂度:O(n log n) 稳定性:稳定
图解
/**以数组 int [] data = {6,5,3,7,8,2,3,1}; 为例 归并排序图解
* { 6, 5, 3, 7, 8, 2, 3, 1}
* 拆分一次 { 6, 5, 3, 7} ↓ { 8, 2, 3, 1,}
* 拆分二次 { 6, 5} { 3, 7} ↓ { 8, 2} { 3, 1}
* 拆分三次 {6} {5} {3} {7} ↓ {8} {2} {3} {1}
* 合并一次 { 5, 6} { 3, 7} ↓ { 2, 8} { 1, 3}
* 合并二次 { 3, 5, 6, 7} ↓ { 1, 2, 3, 8}
* 合并三次 { 1, 2, 3, 3, 5, 6, 7, 8}
*/
代码实现
public static void margeSort(int [] arr){
if(arr == null || arr.length < 2) return;
//通过递归的方式对数组进行拆分
splitArray(arr,0,arr.length - 1);
}
public static void splitArray(int [] arr, int start, int end){
if(start < end){
//每次拆分都将数组平均分成两段
int middle = (start + end) / 2;
splitArray(arr,start,middle);
splitArray(arr,middle + 1,end);
//数组拆分完之后需要进行合并
margeArray(arr,start,middle,end);
}
}
public static void margeArray(int [] arr, int start, int middle, int end){
//声明一个临时数组用来存放排好序的临时数据,方便理解和降低代码的复杂度
int [] tmp = new int[arr.length];
//指针指向前半段的第一个位置
int point1 = start;
//指针指向后半段的第一个位置
int point2 = middle + 1;
//制定开始插入的位置
int loc = start;
//两段数组,一段走完则结束循环
while (point1 <= middle && point2 <= end) {
//由于是按照升序排列,所以往临时数组中存放小的元素
if(arr[point1] > arr[point2]){
tmp[loc ++] = arr[point2 ++];
}else {
tmp[loc ++] = arr[point1 ++];
}
}
//处理前半段数组元素没有处理完的情况
while (point1 <= middle) {
tmp[loc ++] = arr[point1 ++];
}
//处理后半段数组元素没有处理完的情况
while (point2 <= end) {
tmp[loc ++] = arr[point2 ++];
}
//将临时数组中的元素存放到原数组
for (int i = start; i <= end; i++) {
arr[i] = tmp[i];
}
}