归并排序
个人认为归并排序和快速排序有相似之处,都是从大数组一步一步化为小数组再分步解决。
归并排序的思想其实很简单,总共分为两步,分与治。
分指的就是将一个大数组一步一步变小,总体化小再化小,如下图本是长度为8的数组分为两个长度为4的数组再一步一步分下去直到8个数字。
核心代码
1 if(first<last)
2 {
3 int mid=(first+last)/2;
4 mergesort(a,first,mid,temp); //左边有序
5 mergesort(a,mid+1,last,temp); //右边有序
6 mergearray(a,first,mid,last,temp); //再将两个有序数组合并
7 }
8
治就是将小的数组排好序,再一步步整合为大的数组。
之所以要先不断分隔,是为了左右两侧内部要保证有序,才可以进行归并操作。
核心代码
1 while(i<=m&&j<=n)
2 {
3 if(a[i]<a[j])
4 temp[k++]=a[i++];
5 else
6 temp[k++]=a[j++];
7 }
8 while(i<=m)
9 temp[k++]=a[i++];
10 while(j<=n)
11 temp[k++]=a[j++];
12 for(i=0;i<k;i++)
13 a[first+i]=temp[i];

/ 图源于 https://blog.csdn.net/qq_41900081/article/details/86776586
动态图
// 图源于 https://blog.csdn.net/qq_40907279/article/details/81607634
归并排序的时间复杂度为O(nlogn) ,因为递归(分)每次按照一半分区(八个变四个)。最重要的是该算法中最好、最坏和平均的时间性能都是O(nlogn)。
快速排序虽然时间复杂度为O(nlogn)但是有特殊情况。 相比较就是因为归并排序使用空间换时间。
完整代码
1 #include<stdio.h>
2 #include<stdlib.h>
3 long long int ans=0;
4 void memerge(long long int *s, int start, int end)
5 {
6 int mid=(start+end)/2;
7 if(start<end)
8 {
9 memerge(s,start,mid);
10 memerge(s,mid+1,end);
11 }
12 int n[65599];
13 int i,j,k;
14 for(i=start,j=1,k=0;i<=mid&&mid+j<=end;)
15 {
16 if(s[i]>s[mid+j])
17 {
18 ans+=(mid-i+1);
19 n[k++]=s[mid+j++];
20 }
21 else
22 {
23 n[k++]=s[i++];
24 }
25 }
26 while(i<=mid)n[k++]=s[i++];
27 while(mid+j<=end)n[k++]=s[mid+j++];
28 for(i=start,k=0;k<end-start+1;k++)
29 s[i+k]=n[k];
30 }
31
32 int main()
33 {
34 int n,i,j;
35 long long int *s;
36 scanf("%d",&n);
37 s=(long long int *)malloc(sizeof(long long int)*n);
38 for(i=0;i<n;i++)
39 {
40 scanf("%lld",s+i);
41 }
42 memerge(s,0,n-1);
43 printf("%lld\n",ans);
44 ans=0;
45 }
归并排序还可以用在求逆序数中的题目,而快速排序则8太行。
来源:https://www.cnblogs.com/johnfllora/p/12231013.html