归并排序—Merge

  归并排序是一种基于分治法的一种排序方法。它将要排序的序列分成两个长度相等的子序列,为每一个子序列进行排序,然后再将子序列合并成一个有序的序列。
描述

实现:

////////////////////////////////////////////////////////////
//归并排序
//时间复杂度:O(N * logN)
//空间复杂度:O(N)
//稳定性:稳定排序
////////////////////////////////////////////////////////////

//第一个区间:[beg, mid)
//第二个区间:[mid, end)
void _MergeArray(int array[], int64_t beg, int64_t mid, int64_t end, int* tmp){
    int64_t cur1 = beg;
    int64_t cur2 = mid;
    int64_t tmp_index = beg;
    while(cur1 < mid && cur2 < end){
        if(array[cur1] < array[cur2]){
            tmp[tmp_index++] = array[cur1++];
        }else{
            tmp[tmp_index++] = array[cur2++];
        }
    }
    if(cur1 < mid){
        while(cur1 < mid){
            tmp[tmp_index++] = array[cur1++];
        }
    }else{
        while(cur2 < end){
            tmp[tmp_index++] = array[cur2++];
        }
    }
    while(cur1 < mid){
        tmp[tmp_index++] = array[cur1++];
    }
    while(cur2 < end){
        tmp[tmp_index++] = array[cur2++];
    }
    memcpy(array + beg, tmp + beg, sizeof(int) * (end - beg));
}

void _MergeSort(int array[], int64_t beg, int64_t end, int* tmp){
    if(end - beg <= 1){
        return;
    }
    int64_t mid = beg + (end - beg) / 2;
    _MergeSort(array, beg, mid, tmp);
    _MergeSort(array, mid, end, tmp);
    //先保证左右区间均为有序区间后,才能进行合并
    _MergeArray(array, beg, mid, end, tmp);
}

void MergeSort(int array[], int64_t size){
    int* tmp = (int*)malloc(sizeof(int) * size);
    //[0, size)
    _MergeSort(array, 0, size, tmp);
    free(tmp);
}

//归并排序的非递归版本
void MergeSortByLoop(int array[], int64_t size){
    if(size <= 1){
        return;
    }
    int* tmp = (int*)malloc(sizeof(int) * size);
    int64_t gap = 1;
    for(; gap < size; gap *= 2){
        int64_t i = 0;
        for(; i < size; i += gap * 2){
            //每次循环其实就是在处理两个相邻的区间
            int64_t beg = i;
            int64_t mid = i + gap;
            int64_t end = i + 2 * gap;
            if(mid > size){
                mid = size;
            }
            if(end > size){
                end = size;
            }
            //[beg, mid),[mid, end)
            _MergeArray(array, beg, mid, end, tmp);
        }
    }
    free(tmp);
}

优化:
当划分的子区间的元素小于13个元素左右时,再使用归并的话会效率不会很高,相当于多增加了二叉树的后面几层的结点。这时候我们改用直接插入排序来进行优化。

void _MergeArray(int array[], int64_t beg, int64_t mid, int64_t end, int* tmp){
    int64_t cur1 = beg;
    int64_t cur2 = mid;
    int64_t tmp_index = beg;
    while(cur1 < mid && cur2 < end){
        if(array[cur1] < array[cur2]){
            tmp[tmp_index++] = array[cur1++];
        }else{
            tmp[tmp_index++] = array[cur2++];
        }
    }
    if(cur1 < mid){
        while(cur1 < mid){
            tmp[tmp_index++] = array[cur1++];
        }
    }else{
        while(cur2 < end){
            tmp[tmp_index++] = array[cur2++];
        }
    }
    while(cur1 < mid){
        tmp[tmp_index++] = array[cur1++];
    }
    while(cur2 < end){
        tmp[tmp_index++] = array[cur2++];
    }
    memcpy(array + beg, tmp + beg, sizeof(int) * (end - beg));
}

void _MergeSort(int array[], int64_t beg, int64_t end, int* tmp){
    if(end - beg <= 1){
        return;
    }
    int64_t mid = beg + (end - beg) / 2;
    if(begin < mid){
        if(mid - begin > 13){
             _MergeSort(array, beg, mid, tmp);
        }
        else{
            InsertSort(array + beg, end - beg + 1);
        }
    }

    if(mid + 1 < end){
        if(end - mid - 1 > 13){
             _MergeSort(array, mid, end, tmp);
        }
        else{
            InsertSort(array + mid + 1, end - mid);
        }
    }
    //先保证左右区间均为有序区间后,才能进行合并
    _MergeArray(array, beg, mid, end, tmp);
}

void MergeSort(int array[], int64_t size){
    int* tmp = (int*)malloc(sizeof(int) * size);
    //[0, size)
    _MergeSort(array, 0, size, tmp);
    free(tmp);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值