分治法------归并排序代码+测试(非伪代码)

来源:互联网 发布:音频裁剪软件 编辑:程序博客网 时间:2024/05/17 03:47

归并排序算法是用分治策略实现对n个元素进行排序的算法。基本思想是:将R[0........n-1]看成是n个长度为1 的有序序列,然后进行两两归并。得到n/2(这里是向上取整)个长度为2(最后一个有序序列的长度可能为1)的有序序列,再进行两两归并,得到n/4个长度为4(最后一个可能长达小于4)的有序序列,。。。。。。,只到得到一个长度为n的有序序列。归并排序每趟产生的有序区只是局部有序的,也就是说在最后一趟排序结束前,所有元素并不一定归位了。下面直接上代码:

#include <stdio.h>#include <malloc.h>#define MAXE 20//线性表中最多元素个数typedef int KeyType;typedef char InfoType[10];typedef struct       //记录类型{KeyType key;   //关键字项    InfoType data; //其他数据项,类型为InfoType} RecType;void Merge(RecType R[],int low,int mid,int high) //将两个有序表R[low..mid]和R[mid+1..high]归并为一个有序表R[low..high]中{RecType *R1;int i=low,j=mid+1,k=0; //k是R1的下标,i、j分别为第1、2段的下标R1=(RecType *)malloc((high-low+1)*sizeof(RecType));  //动态分配空间while (i<=mid && j<=high)     //在第1段和第2段均未扫描完时循环if (R[i].key<=R[j].key)    //将第1段中的记录放入R1中{R1[k]=R[i];i++;k++; }        else                       //将第2段中的记录放入R1中{R1[k]=R[j];j++;k++; }    while (i<=mid)             //将第1段余下部分复制到R1{   R1[k]=R[i];i++;k++; }    while (j<=high)                //将第2段余下部分复制到R1{R1[k]=R[j];j++;k++;  }    for (k=0,i=low;i<=high;k++,i++) //将R1复制回R中    R[i]=R1[k];} void MergePass(RecType R[],int length,int n)//实现一趟归并{int i;for (i=0;i+2*length-1<n;i=i+2*length) //归并length长的两相邻子表Merge(R,i,i+length-1,i+2*length-1);    if (i+length-1<n)                //余下两个子表,后者长度小于lengthMerge(R,i,i+length-1,n-1);  //归并这两个子表}void MergeSort(RecType R[],int n)  //二路归并排序算法{int length,k,i=1;//i用于累计归并的趟数for (length=1;length<n;length=2*length){MergePass(R,length,n);printf(" 第%d趟归并:",i++);//输出每一趟的排序结果for (k=0;k<n;k++)printf("%4d",R[k].key);printf("\n");}}int main(){int i,k,n=16;KeyType a[]={18,2,20,34,12,32,6,16,5,8,96,32,17,11,7,66};RecType R[MAXE];for (i=0;i<n;i++)R[i].key=a[i];printf("初始关键字:");//输出初始关键字序列for (k=0;k<n;k++)printf("%4d",R[k].key);printf("\n");MergeSort(R,n);printf("最后结果:  ");//输出初始关键字序列for (k=0;k<n;k++)printf("%4d",R[k].key);printf("\n");scanf("%d",&i); return 0; }


 

0 0