归并排序具体原理网上已经有很多大佬分享了,请自行学习,这里主要分享代码。
1.空间复杂度为O(nlogn)的方法
/*
* 空间复杂的为O(nlogn)
* */
private void merge1(E[] L, int low, int mid, int hight, String ascOrDesc) {
/* 存储排序后的数组*/
List<E> temp = new ArrayList<>();
/*将待排序的数组L分成L[low, mid]和L[mid + 1, hight]*/
int i = low;
int j = mid + 1;
/*将L[low, mid]和L[mid + 1, hight]归并成有序的数组存入temp*/
while (i <= mid && j <= hight) {
if(ascOrDesc == "asc"){
if (L[i].compareTo(L[j]) < 0) {
temp.add(L[i]);
i++;
} else {
temp.add(L[j]);
j++;
}
}else{
if (L[i].compareTo(L[j]) > 0) {
temp.add(L[i]);
i++;
} else {
temp.add(L[j]);
j++;
}
}
}
/*当i <= mid 则将L[low, mid]中剩下的元素存入temp*/
while (i <= mid) {
temp.add(L[i]);
i++;
}
/*当i <= mid 则将L[mid + 1, hight]中剩下的元素存入temp*/
while (j <= hight) {
temp.add(L[j]);
j++;
}
/*更新L[low, hight]*/
for (int k = low; k <= hight; k++) {
L[k] = temp.get(k - low);
}
}
2.空间复杂度为O(1)的方法,以插入排序的方法实现归并排序将不会引入额外的数组temp
private void merge2(E[] L, int low, int mid, int hight, String ascOrDesc){
/*将L[mid + 1, hight]以插入排序的方式插入到L[low, mid]中*/
for(int i = mid + 1; i <= hight; i++){
if(ascOrDesc == "asc"){
if(L[i].compareTo(L[i - 1]) < 0){
E temp = L[i];
int f = i;
for(int j = i - 1; j >= low ; j--){
if(L[j].compareTo(temp) > 0){
L[j + 1] = L[j];
f = j;
}
}
L[f] = temp;
}
}else{
if(L[i].compareTo(L[i - 1]) > 0){
E temp = L[i];
int f = i;
for(int j = i - 1; j >= low ; j--){
if(L[j].compareTo(temp) < 0){
L[j + 1] = L[j];
f = j;
}
}
L[f] = temp;
}
}
}
}
递归实现递归排序:
public void mergeSortByRecusion(E[] L, int low, int hight, String ascOrDesc) {
int mid = (low + hight) / 2;
if (low < hight) {
mergeSortByRecusion(L, low, mid, ascOrDesc);
mergeSortByRecusion(L, mid + 1, hight, ascOrDesc);
merge2(L, low, mid, hight, ascOrDesc);
}
}
非递归实现归并排序:
public void mergeSortByUnRecusion(E[] L){
int k = 1;
while(k <= L.length - 1){
mergePass(L, k);
k = k * 2;
mergePass(L, k);//多执行一次是因为当2 * k大于L.length-1的时候,L[k, lenght - 1]就不进行排序了,最后一次执行就是要对这部分进行排序。
}
}
public void mergePass(E[] L, int len){
int temp = 0;
while(temp <= L.length - 1){
int mid = (temp + temp + len - 1) / 2;
if((temp + len - 1) <= L.length - 1){
merge2(L, temp, mid, temp + len - 1, "desc");
}else{
break;
}
temp += len;
}
merge2(L, temp, (temp + L.length - 1) / 2, L.length - 1, "desc");
}