c语言写归并排序

归并排序,在实际开发中,很少用,但是为什么一定要掌握它,甚至在面试中经常会问到。

其实,只是为了更好的理解算法。归并排序最核心的就是分治策略,所谓分治,就是把一个问题,拆分成若干个小问题然后求解。掌握归并排序以后,在遇到更复杂的问题,我们可以考虑分治策略。

归并排序是稳定的,时间复杂度是O(nlogn),空间复杂度是O(n)。

废话少说了,以下是我画的丑陋的分治图,凑合看吧。

以下是c代码:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

/*
*@func:合并被middle分割的两个数组,以下称为左右两部分
*@input:data数组,start开始位置,middle中间位置,end结束位置
*@output:void
*/
void  merger(int *data,int start,int middle,int end){
    int i = start;//左边开始位置
    int j = middle+1;//右边开始位置
    int len = end-start+1;
    //动态申请内存,毕竟int temp[len] 的方式可能会栈内存不足
    int *temp = (int *)malloc(sizeof(int)*len);
    if(temp == NULL)
	    return ;
    int k = 0;
    //开始合并,这里是升序
    while(i <= middle && j <= end){
         if(data[i] < data[j]){
            temp[k++] = data[i++];
         }else{
            temp[k++] = data[j++];
         }         
    }

    //检查左边部分是否合并完
    while(i <= middle){
        temp[k++] = data[i++];
    }
    
    //检测右边部分是否合并完
    while(j <= end){
          temp[k++] = data[j++];
    }
    
    //把有序的temp数组中的数据复制到我们要的data数组中
    memcpy(&data[start],temp,sizeof(int)*len);
    free(temp);
}


void mergerSort(int *data,int start,int end){
    int middle = start + (end - start)/2;
    //使用递归,分治法,先分若干小组,然后再合并成大的有序数组
    if(start < end){
        mergerSort(data, start,middle);//左边部分
        mergerSort(data, middle+1, end);//右边部分
        merger(data, start, middle, end);//合并左右两部分数据
    }
}

void call_merger_sort(int *data,int size){
    if(data == 0 || size <=0)
        return ;
    mergerSort(data,0,size-1);
}

void show_numbers(int *data,int size){
    int i = 0;
    for(;i < size;++i){
        printf("%d ",data[i]);
    }
    printf("\n");    
}

//test...
int main(void ){   
    int data[]={9,2,5,1,3,8,7,6,4,0,999,21,567,23,88,1000,301,100};
    int size = sizeof(data)/sizeof(data[0]);
    printf("start sort:\n");
    show_numbers(data,size);
    sort(data, size);
    printf("end sort:\n");
    show_numbers(data, size);  
}

输出结果:

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值