归并排序的3种实现

归并排序适用于外部排序,是一种稳定的排序。算法很很好的体现了分治法的思想。
时间复杂度O(nlogn)(最好最坏平均都是它)
空间复杂度O(n) (如果使用的是链表,空间复杂度为O(1))

数组递归实现:

void Merge(int* arr,int* tmp,int left,int right,int rightEnd){
    int leftEnd = right-1;
    int start = left;
    int len = rightEnd - left + 1;
    while (left<=leftEnd && right<=rightEnd)
    {
        if (arr[left] > arr[right]){
            tmp[start++] = arr[right++];
        }
        else{
            tmp[start++] = arr[left++];
        }
    }
    while (left <= leftEnd)
    {
        tmp[start++] = arr[left++];
    }
    while(right<=rightEnd){
        tmp[start++] = arr[right++];
    }
    for (int i = 0; i < len; i++, rightEnd--){
        arr[rightEnd] = tmp[rightEnd];
    }
}
void split(int* arr,int* tmp,int left,int rightEnd){
    if (left < rightEnd){
        int center = (rightEnd + left) / 2;
        split(arr, tmp, left, center);
        split(arr, tmp, center + 1, rightEnd);
        Merge(arr, tmp, left, center + 1, rightEnd);
    }
}
void Merge_Sort(int* arr,int len){
    int *tmp = (int*)malloc(sizeof(int)*len);
    split(arr,tmp,0,len-1);
    free(tmp);
}

数组非递归实现:

void Merge(int* arr,int* tmp,int left,int right,int rightEnd){
    int leftEnd = right - 1;
    int start = left;
    while (left <= leftEnd && right <= rightEnd){
        if (arr[left] > arr[right]){
            tmp[start++] = arr[right++];
        }
        else{
            tmp[start++] = arr[left++];
        }
    }
    while (left <= leftEnd){
        tmp[start++] = arr[left++];
    }
    while (right <= rightEnd){
        tmp[start++] = arr[right++];
    }
}
void MergeSort(int* arr,int* tmp,int n,int length)//length当前有序子列的长度
{
    int i;
    for (i = 0; i <= n - 2 * length; i += 2 * length){
        Merge(arr,tmp,i,i+length,i+2*length-1);
    }
    //最后剩下两个子列,进行归并
    if (i + length < n){
        Merge(arr,tmp,i,i+length,n-1);
    }
    else{//只剩最后一个子列,不能成对
        for (int j = i; j < n; j++){
            tmp[j] = arr[j];
        }
    }
}
void Merge_Sort(int* arr,int n){
    int lenght = 1;
    int* tmp = (int *)malloc(sizeof(int)*n);
    while (lenght < n){
        MergeSort(arr,tmp,n,lenght);
        lenght *= 2;
        MergeSort(tmp,arr,n,lenght);
        lenght *= 2;
    }
    free(tmp);
}

链表实现:

void Merge(ListNode* &left,ListNode* right){
    ListNode* tmp = NULL;
    ListNode* head = new ListNode(0);
    head->next = left;
    ListNode* leftPre = head;
    while (left != NULL && right != NULL){
        if (left->val > right->val){
            tmp = right->next;
            leftPre->next = right;
            right->next = left;
            leftPre = leftPre->next;
            right = tmp;
        }
        else{
            leftPre = left;
            left = left->next;
        }
    }
    while (right!= NULL){
        leftPre->next = right;
        leftPre = leftPre->next;
        right = right->next;
    }
    left = head->next;
    delete head;
}
//对链表进行分割
void split(ListNode* &left,ListNode* &right,ListNode* pHead){
    ListNode* low = pHead;
    ListNode* high = pHead;
    while (high->next != NULL && high->next->next != NULL){
        low = low->next;
        high = high->next->next;
    }
    left = pHead;
    right = low->next;
    low->next = NULL;
}
void Merge_Sort(ListNode* &pHead){
    if (pHead == NULL || pHead->next==NULL){
        return;
    }
    ListNode* left = NULL;
    ListNode* right = NULL;
    split(left,right,pHead);
    Merge_Sort(left);
    Merge_Sort(right);
    Merge(left,right);
    pHead = left;//更新pHead
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值