举例讲解C语言对归并排序算法的基础使用

所属分类: 软件编程 / C 语言 阅读数: 46
收藏 0 赞 0 分享

基础概念
百度百科是这么描述归并排序的:
归并操作(merge),也叫归并算法,指的是将两个已经排序的序列合并成一个序列的操作。
设有数列

{6,202,100,301,38,8,1}

初始状态:

[6] [202] [100] [301] [38] [8] [1] 

比较次数 

  i=1 [6 202 ] [ 100 301] [ 8 38] [ 1 ] 3
 
  i=2 [ 6 100 202 301 ] [ 1 8 38 ] 4
 
  i=3 [ 1 6 8 38 100 202 301 ] 4

总计: 11次

实例

#include <stdio.h> 
void printArr(int arr[],int length){ 
    int i; 
    for(i=0;i<length;i++){ 
        printf("%d,",arr[i]); 
    } 
    printf("\n"); 
} 
void merge(int a[],int alength,int b[],int blength,int c[]){//将2个已排好序的数组合并到数组c 
    int i=0,j=0,k=0; 
    while(1){ 
        if(a[i]<=b[j]){ 
            c[k] = a[i]; 
            i++; 
            k++; 
            if(i==alength){ 
                for(;j<blength;j++,k++){ 
                    c[k] = b[j]; 
                } 
                break; 
            } 
        }else{ 
            c[k] = b[j]; 
            j++; 
            k++; 
            if(j==blength){ 
                for(;i<alength;i++,k++){ 
                    c[k] = a[i]; 
                } 
                break; 
            } 
        } 
    } 
    printArr(c,k); 
 
} 
void mergeSort(int arr[],int length){//将一个数组分成2个数组,前length-1为第一个,最后一个为第二个,然后合并2个数组 
    if(length > 1){ 
        int arr1[length-1],arr2[1] = {arr[length-1]}; 
        int i; 
        for(i=0;i<length-1;i++){ 
            arr1[i] = arr[i]; 
        } 
        mergeSort(arr1,length-1);//递归的调用自己 
        merge(arr1,length-1,arr2,1,arr); 
    } 
} 
 
int main(void){ 
    int a[10] = {3,54,16,8,123,8,89,23,87,2}; 
    printArr(a,10); 
    mergeSort(a,10); 
    return 0; 
 
} 

算法性能/复杂度
归并排序的效率是很高的,由于递归划分为子序列只需要logN复杂度,而合并每两个子序列需要大约2n次赋值,为O(n)复杂度,因此,只需要简单相乘即可得到归并排序的时间复杂度 O(㏒n)。并且由于归并算法是固定的,不受输入数据影响,所以它在最好、最坏、平均情况下表现几乎相同,均为O(㏒n)。
但是,归并排序最大的缺陷在于其空间复杂度。从上面的代码可以看到,在合并子数组的时候需要一个辅助数组,然后再把这个数据拷贝回原数组。所以,归并排序的空间复杂度(额外空间)为O(n)。可不可以省略这个数组呢?不行!如果取消辅助数组而又要保证原来的数组中数据不被覆盖,那就必须要在数组中花费大量时间来移动数据。不仅容易出错,还降低了效率。因此这个辅助空间是少不掉的。

算法稳定性
因为我们在遇到相等的数据的时候必然是按顺序“抄写”到辅助数组上的,所以,归并排序同样是稳定算法。

算法适用场景
归并排序在数据量比较大的时候也有较为出色的表现(效率上),但是,其空间复杂度O(n)使得在数据量特别大的时候(例如,1千万数据)几乎不可接受。而且,考虑到有的机器内存本身就比较小,因此,采用归并排序一定要注意。

更多精彩内容其他人还在看

详解C++ string字符串类

这篇文章主要介绍了C++ string字符串类,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
收藏 0 赞 0 分享

C++单例类模板详解

这篇文章主要介绍了C++单例类模板,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
收藏 0 赞 0 分享

C语言实现数据结构迷宫实验

这篇文章主要为大家详细介绍了C语言实现数据结构迷宫实验,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
收藏 0 赞 0 分享

C语言数据结构之迷宫问题

这篇文章主要为大家详细介绍了C语言数据结构之迷宫问题,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
收藏 0 赞 0 分享

C语言数据结构之迷宫求解问题

这篇文章主要为大家详细介绍了C语言数据结构之迷宫求解问题,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
收藏 0 赞 0 分享

C语言实现小学生考试系统

这篇文章主要为大家详细介绍了C语言实现小学生考试系统,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
收藏 0 赞 0 分享

C语言实现小学生随机出题测试计分

这篇文章主要为大家详细介绍了C语言实现小学生随机出题测试计分,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
收藏 0 赞 0 分享

C语言实现小学生计算机辅助教学系统

这篇文章主要为大家详细介绍了C语言实现小学生计算机辅助教学系统,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
收藏 0 赞 0 分享

详解C++中构造函数,拷贝构造函数和赋值函数的区别和实现

这篇文章主要介绍了C++中构造函数,拷贝构造函数和赋值函数的区别和实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
收藏 0 赞 0 分享

C语言清除scanf()缓存的案例讲解

今天小编就为大家分享一篇关于C语言清除scanf()缓存的案例讲解,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
收藏 0 赞 0 分享
查看更多