浅谈归并排序

归并排序

归并排序(MERGE-SORT)是利用归并的思想实现的排序方法,该算法采用经典的分治法,并且归并排序在排序过程中,相同的元素并没有改变,所以归并排序也是一种稳定的排序算法。

算法思路

将原数组递归分成若干个子数组,当两个子数组分别只有一个元素的时候,我们要把这些子数组变成有序的,将若干组两两合为更长的有序表。重复这一步直到合并为一个有序表。

详细思路

先设置递归出口,如果l数大于r数则交换这两个数(r 代表right, l 代表left),在回溯的时候合并。首先要开辟一片大小为(r - l + 1)临时数组。在定义两个指针p1, p2分别指向两个数组的头指针,比较两个指针指向的元素,选择比较小的元素放入temp数组内,并向下一个目标移动。最后依次

将temp替换原数组。

/*************************************************************************
	> File Name: stable_sort.c
 ************************************************************************/

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<time.h>
#define swap(a, b)\
{\
    __typeof(a) temp = a;\
    a = b; b = temp;\
}

void merge_sort(int *num, int l, int r)
{
    if(r - l <= 1)
    {
        if(r - l == 1 && num[r] < num[l])
        swap(num[r], num[l]);
        return ;
    }
    //分成两半递归
    int mid = (l + r) >> 1;
    merge_sort(num, l, mid);
    merge_sort(num, mid + 1, r);
    int *temp = (int *)malloc(sizeof(int) * (r - l + 1));
    int k = 0, p1 = l, p2 = mid + 1;
    //将有序表合并依次存入temp中
    while(p1 <= mid || p2 <= r)
    {
        if(p2 > r || (p1 <= mid && num[p1] <= num[p2]))
        temp[k++] = num[p1++];
        else
        temp[k++] = num[p2++];
    }
    //将temp存入num地址的基础上后移l的那段空间
    memcpy(num + l, temp, sizeof(int) * (r - l + 1));
    free(temp);
    return ;
}

void output(int *num, int n)
{
    printf("[");
    for(int i = 0; i < n; i++)
    {
        i && printf(",");
        printf("%d",num[i]);       
    }
    printf("]\n");
}

int main()
{
    srand(time(NULL));
    #define INT_MAX 20
        
    int num[INT_MAX];
    for(int i = 0; i < INT_MAX; i++)
    {
        num[i] = rand() % 100;
    }
   
    output(num, INT_MAX);

    merge_sort(num, 0, INT_MAX - 1);
    
    output(num, INT_MAX);
    
    #undef INT_MAX
    return 0;
}

复杂度

归并排序每次都要将数组拆分一半进行排序,一共需要(logn)轮,每轮都遍历(n)次,所以该算法的时间复杂度为O(nlogn)。在归并排序算法过程中,需要开辟额外的数组去存储排序后的结果,所占空间为n,因此空间复杂度为O(n)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值