• 归并排序(C语言)


    归并排序其实要做两件事:

    (1)“分解”——将序列每次折半划分。

    (2)“合并”——将划分后的序列段两两合并后排序。

    具体过程如下图所示:

     

    算法的时间复杂度是O(N*lgN),空间复杂度是O(N)。

    本文会使用递归及非递归方式实现归并排序算法

    递归版本

    #define _CRT_SECURE_NO_WARNINGS
    #include <stdio.h>
    #include <stdlib.h>
    #include <stdio.h>
    
    typedef int RecType;//要排序元素类型
    /// <summary>
    /// 将两个有序的子文件R[low..m)和R[m+1..high]归并成一个有序的子文件R[low..high]  
    /// </summary>
    /// <param name="R">数组</param>
    /// <param name="low"></param>
    /// <param name="m">中间位置</param>
    /// <param name="high"></param>
    void Merge(RecType *R, int low, int m, int high)
    {
        //置初始值    p是新向量的计数
        int i = low, j = m + 1, p = 0;                  
        RecType *R1; 
        //R1是局部向量  
        R1 = (RecType *)malloc((high - low + 1)*sizeof(RecType));
        //申请空间失败  
        if (!R1)
        {
            return;                        
        }
        //两子文件非空时取其小者输出到R1[p]上 
        while (i <= m&&j <= high)                 
        {
            R1[p++] = (R[i] <= R[j]) ? R[i++] : R[j++];
        }
        //若第1个子文件非空,则复制剩余记录到R1中  
        while (i <= m)                         
        {
            R1[p++] = R[i++];
        }
        //若第2个子文件非空,则复制剩余记录到R1中  
        while (j <= high)                      
        {
            R1[p++] = R[j++];
        }
        //归并完成后将结果复制回R[low..high]  
        for (p = 0, i = low; i <= high; p++, i++)
        {
            R[i] = R1[p];                     
        }
    }
    
    void MergeSort(RecType R[], int low, int high)
    {
        //用分治法对R[low..high]进行二路归并排序  
        int mid;
        if (low<high)
        {   //区间长度大于1   
            mid = (low + high) / 2;               //分解  
            MergeSort(R, low, mid);           //递归地对R[low..mid]排序  
            MergeSort(R, mid + 1, high);        //递归地对R[mid+1..high]排序  
            Merge(R, low, mid, high);          //组合,将两个有序区归并为一个有序区  
        }
    }
    
    void main()
    {
        int a[7] = { 49, 38, 65, 97, 76, 13, 27 }; //这里对7个元素进行排序  
        int low = 0, high = 6;                   //初始化low和high的值  
    
        printf("Before merge sort: 
    ");
        for (int i = low; i <= high; i++)
        {
            printf("%d ", a[i]);             //输出测试  
        }
        printf("
    ");
    
        MergeSort(a, low, high);
    
        printf("
     After merge sort: 
    ");
        for (int i = low; i <= high; i++)
        {
            printf("%d ", a[i]);             //输出测试  
        }
        printf("
    ");
    }

    非递归版

    非递归版的归并排序,省略了中间的栈空间,直接申请一段O(n)的地址空间即可,因此空间复杂度为O(n),时间复杂度为O(nlogn);

    #define _CRT_SECURE_NO_WARNINGS
    #include <stdio.h>
    #include <stdlib.h>
    #include <stdio.h>
    #include <time.h>
     
    int arrtest1[10] = {4,3,7,8,0,9,1,2,6,5};
    int arrtest2[10] = {0,1,2,3,4,5,6,7,8,9};
    int arrtest3[10] = {9,8,7,6,5,4,3,2,1,0};
    void copy(int *from,int *arr,int length);
    void print(int *arr,int length);
    static void MergeSort(int *arr,int length);
    static void Merge(int *arr1,int *temp,int k,int length);
    void sort(int *arr,int *temp,int begin,int m,int end);
    
    int main(){
        int Arr[10],i;
        copy(arrtest1,Arr,10);
        print(Arr,10);
        MergeSort(Arr,10);
        print(Arr,10);
        getchar();
        return 0;
    }
    
    /// <summary>
    ///  以*2自增的归并方法
    /// </summary>
    /// <param name="arr"></param>
    /// <param name="length">数组总长</param>
    void MergeSort(int *arr,int length){
        //分配一个临时数组
        int *temp = (int *)malloc(sizeof(int)*length);
        int i = 1;
        while(i<length){
            Merge(arr,temp,i,length);
            i *= 2;
        }
    }
    
    /// <summary>
    /// 
    /// </summary>
    /// <param name="arr1"></param>
    /// <param name="temp">temp数组</param>
    /// <param name="k">归并因子</param>
    /// <param name="length">总长度</param>
    void Merge(int *arr1,int *temp,int k,int length){
        int i = 0,j;
        //
        while(i <= length-2*k){
            //从i到i+2*k-1排序
            sort(arr1,temp,i,i+k-1,i+2*k-1);
            //以2k为单位自增去排序
            i += 2*k;
        }
        if(i < length-k+1)//如过剩余个数比一个k长度还多...那么就在进行一次合并
            sort(arr1,temp,i,i+k-1,length-1);
        else
            for(j=i;j<length;j++)
                temp[j] = arr1[j];
        //把temp的数据拷贝到原数组
        for(i=0;i<length;i++){
            arr1[i] = temp[i];
        }
    }
    
    /// <summary>
    /// 实际进行排序的方法  temp为排序后的数组,然后在上个方法中统一拷贝到原数组
    /// </summary>
    /// <param name="arr"></param>
    /// <param name="temp"></param>
    /// <param name="begin">开始位置</param>
    /// <param name="m">中间位置</param>
    /// <param name="end">结束位置</param>
    void sort(int *arr,int *temp,int begin,int m,int end){
        //j=m+1 为后半区 j控制是否超限    
        //k为temp数组的索引游标
        int i=begin,j=m+1,k,h;
        //判断条件为i小于中间位置且j小于结束位置   k位置每次加1
        for(k=i; i<=m && j<=end;k++){
            //判断开始位置和增量+1位置的大小,把较小的赋值给temp
            if(arr[i] < arr[j])
                //j位置+1
                temp[k] = arr[i++];
            else
                temp[k] = arr[j++];
        }
        if(i <= m){
            for(h=0; h<=m-i;h++)
                temp[k+h] = arr[i+h];
        }else{
            for(h=0; h<=end-j;h++)
                temp[k+h] = arr[j+h];
        }
    }
    
    /// <summary>
    /// 
    /// </summary>
    /// <param name="from"></param>
    /// <param name="to"></param>
    /// <param name="length"></param>
    void copy(int *from,int *to,int length){
        int i;
        for(i=0;i<length;i++){
            to[i] = from[i];
        }
    }
    
    void print(int *arr,int length){
        int i;
        for(i=0;i<length;i++){
            printf("%d ",arr[i]);
        }
        printf("
    ");
    }
  • 相关阅读:
    【并查集】hdu 1198 Farm Irrigation
    【并查集】hdu 1325 Is It A Tree?
    【并查集】hdu 1272 小希的迷宫
    【并查集】hdu 1856 More is better
    【并查集】hdu 3635 Dragon Balls
    【并查集】poj 1988 Cube Stacking
    【并查集】poj 2492 A Bug's Life(二集合问题)
    【并查集】poj 2236 Wireless Network
    【并查集】poj 1703 Find them, Catch them(二集合问题)
    【并查集】poj 1611 The Suspects
  • 原文地址:https://www.cnblogs.com/qixinbo/p/7856012.html
Copyright © 2020-2023  润新知