归并排序使用递归算法实现比较简单,但是递归调用比较浪费资源,所以使用循环迭代实现了一下java代码:
public class MergeSort {
public static void main(String[] args) {
int[] arr = new int[] {23, 13, 43, 25, 64, 44, 9, 1, 39};
sort(arr);
for(int a: arr) {
System.out.print(a + " ");
}
}
public static void sort(int[] arr) {
int k, ll, lr, rl, rr;
int[] temp = new int[arr.length];
for(int i = 1; i <= arr.length / 2; i *= 2) {
for(ll = 0; ll < arr.length - i; ll = rr) {
lr = ll + i;
rl = lr;
rr = rl + i;
if(rr > arr.length) {
rr = arr.length;
}
k = 0;
while(ll < lr && rl < rr) { // 归并,直到有一边排完
if(arr[ll] < arr[rl]) {
temp[k++] = arr[ll++];
} else {
temp[k++] = arr[rl++];
}
}
while(ll < lr) { // 如果是左边有剩余,剩余的是最大的,直接依次排在最右边
// 插入前rl == rr,为了与右边有剩余的情况兼容,使用rl替代最右边标志位
arr[--rl] = arr[--lr];
} // 如果是右边有剩余,则剩余的刚好是较大的排序,不用操作
while(k > 0) { // 将前面排好序的数依次放回原数组
arr[--rl] = temp[--k];
}
}
}
}
// 上面的代码是最终的优化结果,
// 下面的是最开始时写的迭代方法, 还是比较浪费效率
// 贴出来给自己做一个前后的对比
/* public static void sort(int[] arr) {
int[] temp = new int[arr.length];
for(int i = 1; i <= arr.length / 2; i *= 2) {
int k = 0, ll = 0, lr= 0, rl = 0, rr = 0;
while(k < arr.length) { // 没有对原数组进行充分的利用, 而是对中间数组temp进行迭代计算
ll = rr;
lr = ll + i;
rl = lr;
rr = lr + i;
if(rr > arr.length) {
rr = arr.length;
}
if(lr > arr.length) {
lr = arr.length;
}
while(ll < lr && rl < rr) {
if(arr[ll] < arr[rl]) {
temp[k++] = arr[ll++];
} else {
temp[k++] = arr[rl++];
}
}
while(ll < lr) {
temp[k++] = arr[ll++];
}
while(rl < rr) {
temp[k++] = arr[rl++];
}
}
while(--k >= 0) { // 上面3个步骤需要在原数组arr和中间数组temp之间进行大量的数据复制
arr[k] = temp[k];
}
}
} */
}