学习新算法的时候总会让我感慨学海无涯以及自己的无知。
折腾了整整一天啊。。看了书上的伪码看半天愣是没搞懂,后面还是感谢csdn上博主@一只菜菜的小鸟 看了他的代码 通俗易懂 我才整明白了。
后面也是结合书上的伪码以及他的代码自己实现出来了。
归并排序的思路网上和书上都有很多。
我就不去网上拷图放在这里了。
重点在于:通过递归将原序列切半直到只剩下两个数据 还有一个能将它们合成排序新序列的函数
我将贴上两段代码,第一段是借鉴那位启蒙我的博主的代码
第二段则是我个人结合他与书上的伪码自己实现出来的代码。
这是第一段:
#include<stdio.h>
#define MAX 100
//数组a看成两半,每一半都是已排序的序列,将它们两个归并起来并排好序放在数组t中
void merge(int a[],int t[],int left,int mid,int right)
{
int i,j,k;
i=left;j=mid+1;k=left;
while(i<=mid&&j<=right)
{
if(a[i]<a[j])
t[k++]=a[i++];
else
t[k++]=a[j++];
}
while(i<=mid)
t[k++]=a[i++];
while(j<=right)
t[k++]=a[j++]; //到此数组t已经被排好序
}
//通过递归将一个完整的序列不断分成左右两个序列,直到序列只剩下一个数据(即left==right)
void msort(int a[],int t[],int left,int right)
{
int s[MAX];
int mid;
if(left==right)
t[left]=a[right];
else
{
mid=(left+right)/2;
msort(a,s,left,mid); //处理左边
msort(a,s,mid+1,right);//处理右边
merge(s,t,left,mid,right);
//s是左右两边合并起来的新序列,通过merge函数将它们归并排序成t序列
}
}
int main()
{
int a[10]={9,8,7,6,5,4,3,2,1},i;
msort(a,a,0,8);
for(i=0;i<9;i++)
printf("%d ",a[i]);
return 0;
}
上面这一段代码通俗易懂,但是有个缺点,那就是在msort函数中申请了中间序列t[] 由于是递归,所以当数据庞大时会造成空间浪费。好在它确实好懂。
下面第二段是我个人的:
#include<stdio.h>
#include<stdlib.h>
/*merge函数 用来将两个已排好序的序列合成一个顺序序列
它的函数参数是固定的,即一个预排列的序列a[] 一个中间序列temp[]用来存放合成的新序列
序列a[]的左端指针left,中部指针mid,右端指针right*/
void merge(int a[],int temp[],int left,int mid,int right)
{
int i,j,k;
i=left;j=mid+1;k=left;
while(i<=mid&&j<=right) //这一段是排序算法
{
if(a[i]<=a[j])
temp[k++]=a[i++];
else
temp[k++]=a[j++];
}
while(i<=mid)
temp[k++]=a[i++];
while(j<=right)
temp[k++]=a[j++];
for(k=left;k<=right;k++) //再将已排好的序列复制回a[]
a[k]=temp[k];
}
/* msort函数 核心函数 使用递归让原序列分割
初始状态下分成n个 然后两两合并,排序
它的参数也是固定的 即一个原序列a[] 一个中间序列t[] 序列a[]的左、右端指针 left 和right */
void msort(int a[],int t[],int left,int right)
{
int mid;
if(left<right)
{
mid=(left+right)/2;
msort(a,t,left,mid); //先处理左半部分
msort(a,t,mid+1,right); //再处理右半部分
merge(a,t,left,mid,right); //归并排序
}
}
/*最终我们需要申请一个中间序列 它在调用msort函数以及merge函数要用上,最后可以把它free
可以节省空间
当然我们也可以不用写这个函数 而是直接在主函数调用的时候申请即可*/
void MergeSort(int a[],int n)
{
int *t;
t=(int*)malloc(sizeof(int)*n);
if(n>0)
{
msort(a,t,0,n-1);
free(t); //节省空间
}
}
int main()
{
int a[10]={9,8,7,6,5,4,3,2,1},i;
/* int t[10]; 这一段就是没有写最后的函数可以这样用 只是t[]用完其实就没用了 可以free掉
msort(a,t,0,8);*/
MergeSort(a,9);
for(i=0;i<9;i++)
printf("%d\n",a[i]);
return 0;
}
1
2
3
4
5
6
7
8
9
--------------------------------
Process exited after 0.1098 seconds with return value 0
请按任意键继续. . .