排序——归并排序

来源:互联网 发布:nba竞猜软件 编辑:程序博客网 时间:2024/05/22 06:40
    归并(Merge)排序法是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个有序的子序列,再把有序的子序列合并为整体有序序列。归并排序是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。
归并过程:
例如有两个有序表:(7,10,13,15)和(4,8,19,20),归并后得到的有序表为:(4,7,8,10,13,15,19,20)。
归并过程为:比较a[i]和a[j]的大小,若a[i]≤a[j],则将第一个有序表中的元素a[i]复制到r[k]中,并令i和k分别加上1,如此循环下去,直到其中一个有序表取完,然后再将另一个有序表中剩余的元素复制到r中从下标k到下标t的单元。
但是上面这个思路的前提是已经有了两个有序的子表,但是在实际排序过程中往往不可能已经有了两个有序子表,所以最好的办法就是先假设子表的长度都为1,因为一个元素总是有序的,然后通过归并得到更长的子表,依次类推,最终得到一个整体的有序序列。
程序代码如下:
#include <stdio.h>#defineN17void print(int a[], int n){      int j;for(j=0; j < n; j++){          if(a[j])printf("%2d ", a[j]);     }      printf("\n");  }    /*将src[i…m]和src[m +1 …n]归并到辅助数组des[i…n]*/  void two_merge(int *src, int *des, int i, int m, int n)  {      int j, k;    for(j=m+1, k=i; i<=m && j<=n ; k++){          if(src[j] < src[i]) des[k] = src[j++];          else des[k] = src[i++];      }      while(i <= m)  des[k++] = src[i++];      while(j <= n)  des[k++] = src[j++];printf("合并结果:   ");    print(des, N);  }    void merge_sort(int *s, int *d, int length)  {       int step = 1;       int *tmp, *src = s, *des = d; int i;/*先将src[0],src[1]合并为src1,src[2],src[3]合并为src2...,再将src1,src2合并...*/    while(step < length) {             i = 0;step *= 2; /*step的起始步长应该为2*/        while(i+step <= length) /*length/step能够整除的部分先合并*/{              two_merge(src, des, i, i+step/2-1, i+step-1);              i = i + step;          }        if((i+step/2) < length) /*i==length表示刚好整除*/                    /*除不够且能够合并的在这里合并*//*不能合并的状态举例:以step=4合并但是只余了<=2个元素*/{  two_merge(src, des, i, i+step/2-1, length-1); /*i+step/2-1>length-1的时候two_merge函数会排错*/         }          tmp = src; src = des; des = tmp; /*交换src和des数组*/    }}      int main(){      int src[N] = {1, 3, 7, 6, 8, 10, 2, 5, 4, 9, 12, 11, 13, 17, 15, 14, 16};      int des[N] = {0};merge_sort(src, des, N);     printf("排序之后的src:");print(src, N);      printf("排序之后的des:");      print(des, N);  return 0;  } 

程序运行结果:

N=13时


N=17时

分析:从程序输出的结果看,排好序的结果可能最终存放于src数组,也可能最终存放于des数组,这是因为在归并排序的时候,不停的再交换src和des数组,即把一个的合并结果放到另一个数组,另一个的合并结果又反过来放到当前的数组,如此交替,如果需要制定最终结果放到哪个数组,那么可以在merge_sort函数的末尾判断s与src的关系,再进行一次数据复制即可。

归并排序的特点:

时间复杂度:O(nlog(2^n)),因为对于归并排序来说,一个元素比较log(2^n)就会放到最终的位置上,一共有n个元素。

空间复杂度:O(n),用到了一个辅助数组。

稳定性:稳定。

1 0
原创粉丝点击