zoukankan      html  css  js  c++  java
  • 归并排序(merge_sort)的C语言实现

    在Linux下实现了一个归并排序的算法,分成多个文件,这里记录三点:归并排序的算法、makefile的使用、gdb调试心得

    一、归并排序算法

          算法的递推关系:一个大的数列需要排序,把它从中间分成两部分,每一部分归并排序,然后把排好序的这两个部分再合并起来(合并的时候要按顺序合并)。

          算法的Base Case:如果分成的这部分只有一个数,那么这个部分就不用再排序(看做已经排好序的)。

          实现这个算法用了三个函数,每个函数在一个文件中,分别为:merge.c  sort.c 和 main.c,其中merge.c实现的是合并的方法,sort.c实现的是排序的方法,main.c是一个测试实例。还有三个头文件,分别指出了函数原型。

    merge.c:

    /*This is a merge program.
    * Given an integer ARRAY and three numbers which indicate the begain
    *and the end of two subarrays, merge the two subarrays to a bigger
    *one. The two subarrays are alrealy sorted from small to big.
    * For example, given an array a[10] and three numbers 0, 3 and 5. The
    *first array is from a[0] to a[2], the seconde array is from a[3] to
    *a[4]. The number 3 and 5 are the upper side. This program merge the
    *two arrays together.
    *
    *Author: Eric
    *Time: 2011.01.08
    */
    #include <stdio.h>
    #include <stdlib.h>

    #include "main.h"

    void merge(int *a, int idxa, int idxb, int idxc)
    {
    int i = idxa, j = idxb, k = 0;
    int total = idxc-idxa;
    //int temp[total] = {0};
    int *temp = (int *)malloc(sizeof(int) * total);
    if(temp == NULL)
    {
    fprintf(stderr, "malloc error in merge function\n");
    return;
    }
    while(i < idxb && j < idxc)
    {
    if(a[i] < a[j])
    temp[k++] = a[i++];
    else
    temp[k++] = a[j++];
    }

    if(i == idxb)
    {
    while(j < idxc)
    temp[k++] = a[j++];
    }
    else if(j == idxc)
    {
    while(i < idxb)
    temp[k++] = a[i++];
    }

    /*Copy the temp to the sorce array*/
    for(i = 0, k = idxa; i < total; k++, i++)
    a[k] = temp[i];

    free(temp);
    }

    #ifndef MAIN
    /*For test*/
    int main()
    {
    int a[10];
    int i = 0;
    int idxa=1, idxb=5, idxc=8;

    printf("Please input 10 numbers to the array:");
    for(i = 0; i < 10; i++)
    scanf("%d", &a[i]);
    printf("Three indexes are %d, %d and %d.\nThe first subarray is:", idxa, idxb, idxc);
    for(i = idxa; i < idxb; i++)
    printf(" %d", a[i]);
    printf("\nThe second subarray is:");
    for(i = idxb; i < idxc; i++)
    printf(" %d", a[i]);
    printf("\n");

    merge(a, idxa, idxb, idxc);
    printf("The merged array is:");
    for(i = idxa; i < idxc; i++)
    printf(" %d", a[i]);
    printf("\n");

    return 0;
    }
    #endif

    merge.h:

    /*Author:    Eric
    *Time: 2011.01.08
    */

    void merge(int *a, int idxa, int idxb, int idxc);
     

    sort.c:

    /*This is a function for sorting an array useing merge.c
    *
    *Author: Eric
    *Time: 2011.01.08
    */
    #include <stdio.h>

    #include "main.h"
    #include "merge.h"

    /*Sort array a, from a[begin] to a[upend-1]*/
    void sort(int *a, int begin, int upend)
    {
    int n = upend - begin; /*the number to be sorted*/
    /*The first array is a[idxa] to a[idxb-1]. The second is a[idxb] to a[idxc-1]*/
    int idxa = begin,
    idxb = ((begin+upend)%2 == 0) ? (begin+upend)/2 : (begin+upend+1)/2,
    idxc = upend;

    if(n < 2)
    {
    printf("The array elements are less than two. No need to sort\n");
    return;
    }
    else if(n == 2)
    merge(a, idxa, idxb, idxc);
    else
    {
    if(idxb-idxa > 1)
    sort(a, idxa, idxb);
    if(idxc-idxb > 1)
    sort(a, idxb, idxc);
    merge(a, idxa, idxb, idxc);
    }
    }

    #ifndef MAIN
    #define MAIN
    /*For test*/
    int main()
    {
    int a[10] = {1, 4, 8, 5, 10, 25, 54, 15, 12, 2};
    int i = 0;

    sort(a, 0, 10);

    printf("The sorted array is:");
    for(i = 0; i < 10; i++)
    printf(" %d", a[i]);
    printf("\n");

    return 0;
    }
    #endif

    sort.h:

    void sort(int *a, int begin, int upend);

    main.c:

    #include <stdio.h>

    #include "sort.h"

    int main()
    {
    int a[10] = {9, 8, 7, 6, 5, 4, 3, 2, 1, 0};
    int i = 0;

    sort(a, 0, 10);

    printf("The sorted array is:");
    for(i = 0; i < 10; i++)
    printf(" %d", a[i]);
    printf("\n");

    return 0;
    }

    main.h:

    #ifndef MAIN
    #define MAIN
    #endif

    说明:在merge函数以及sort函数中,数组的下标都是非对称的。也就是说,数组是a[begin..upend-1]。所有子数组也是这样定义的。其中idxa的意思是index a。

    这个算法的思想其实很简单,之所以写这么多程序完全是为了练习在在Linux下编程。更简洁的算法实现可以参看归并排序,只不过作者的数组和我的不一样。

    二、makefile的使用

    在Linux下编好多个文件的程序之后要用Makefile文件把它们联合起来,这样这些程序才能组成一个可以执行的程序。我的Makefile文件内容如下:

    main: main.o sort.o merge.o
        gcc $^ -o $@

    main.o: main.c sort.h
    sort.o: sort.c merge.h main.h
    merge.o: merge.c main.h

    clean:
        -rm *.o

    .PHONY: clean

    运行时使用命令make CFLAGS=-g -n可以尝试运行,看Makefile文件有没有写对。真正运行的时候去掉-n选线即可。

    三、gdb调试心得

    display *a@10  这个命令在每次运行的时候列出数组a的10个元素

    设置断点,大段大段的运行程序。

  • 相关阅读:
    HDU.6681.Rikka with Cake(欧拉公式 树状数组)
    Codeforces.449C.Willem, Chtholly and Seniorious(ODT)
    2017-2018 ACM-ICPC, Asia Daejeon Regional Contest (E,G,H,I,K)
    CF GYM.101987A.Circuits(线段树)
    2018-2019 ACM-ICPC Nordic Collegiate Programming Contest (NCPC 2018)
    220
    219
    218
    217
    216
  • 原文地址:https://www.cnblogs.com/wangshuo/p/1930940.html
Copyright © 2011-2022 走看看