归并排序与快排一样也是一种分治的算法,与快排的区别在于是取数组的中间元素分为左右两侧,先把两侧的排序好之后再进行归并。复杂程度只有O(n)。

        先把main函数中的输入输出定义函数完成。

#include

using namespace std;

const int N=1000010;

int n;

int q[N],tmp[N]

int main()

{

scanf("%d",&n);

for(int i=0;i

scanf("%d",&q[i]);

}

merge_sort(q,0,n-1);

for(int i=0;i

printf("%d ",q[i]);

}

return 0;

}

        归并排序最重要的一步就是归并。需要另外开辟一个临时保存数据的数组tmp,merge_sort的函数,它接受三个参数:一个整型数组q、左边界l和右边界r。该函数的作用是对数组q中从下标l到下标r的元素进行排序。函数首先判断左边界是否大于等于右边界,如果是,则说明已经到达了递归的基本情况,直接返回即可。否则,计算中间位置mid,然后递归地对左半部分和右半部分分别进行排序,在左右两部分排好序后,定义两个指针(注意不是真正意义上的指针,是两个标记,可以理解为数组的下标)。一个指向左半部分的首记为 i,另一个指向右半部分的首记为 j,比较q[ i ]和q[ j ]两个位置上数组元素的大小,如果q[ i ]

void merge_sort(int *q,int l,int r)

{

if(l>=r) return;

int mid=l+r>>1;

merge_sort(q,l,mid); merge_sort(q,mid+1,r);

int k=0,i=l,j=mid+1;

while(i<=mid&&j<=r)

if(q[i]<=q[j]) tmp[k++]=q[i++];

else tmp[k++]=q[j++];

while(i<=mid) tmp[k++]=q[i++];

while(j<=r) tmp[k++]=q[j++];

for(int i=l,j=0;i<=r;i++,j++) q[i]=tmp[j];

}

        个人认为归并中的递归排序左右两半部分是比较难理解的。这里用图解来解释。比如先输入9个数据:6 5 7 1 4 3 2 8 9。即传入函数时是 l = 0,r = 8。不满足条件if ( l > = r ),于是取中间值后执行函数本身 merge_sort(q,l,mid); 与 merge_sort(q,mid+1,r);直到分为一个元素之后开始比较,每次递归的返回都将比较的结果填入tmp中直到左右两部分比较完成。

全部代码如下:

#include

using namespace std;

const int N=1000010;

int n;

int q[N],tmp[N];

void merge_sort(int *q,int l,int r)

{

if(l>=r) return;

int mid=l+r>>1;

merge_sort(q,l,mid); merge_sort(q,mid+1,r);

int k=0,i=l,j=mid+1;

while(i<=mid&&j<=r)

if(q[i]<=q[j]) tmp[k++]=q[i++];

else tmp[k++]=q[j++];

while(i<=mid) tmp[k++]=q[i++];

while(j<=r) tmp[k++]=q[j++];

for(int i=l,j=0;i<=r;i++,j++) q[i]=tmp[j];

}

int main()

{

scanf("%d",&n);

for(int i=0;i

scanf("%d",&q[i]);

}

merge_sort(q,0,n-1);

for(int i=0;i

printf("%d ",q[i]);

}

return 0;

}

参考文章

评论可见,请评论后查看内容,谢谢!!!评论后请刷新页面。