归并排序 C语言
思路:分治 先分原数组左半边 再分原数组右半边,最终层层递归治实现排序;图片来自https://blog.csdn.net/baidu_15547923/article/details/89742717
归并与逆序对的关系:以分治的某一个阶段为例
[下标] 0123 4567
[数组] 4578 1236
( start=0, mid=3, end=7 )
左半边 4 > 1就代表一对逆序对,而左半边已经排序完成,即(4,1)、(5,1)、(7,1)、(8,1)都是逆序对,
同理4>2,逆序对有(4,2)、(5,2)、(7,2)、(8,2)…(4,3)、(5,3)、(7,3)、(8,3)…(7,6)、(8,6);最终当左侧大于右侧时,逆序对个数可表达mid-i+1(i为左侧索引,mid为左侧索引的结尾)
LeetCode题型:
LeetCode 493 翻转对
https://blog.csdn.net/qq_40405527/article/details/108074965
LeetCode 327 区间和的个数
https://blog.csdn.net/qq_40405527/article/details/108085048
#include<stdio.h>
#include<stdlib.h>
#define ArrLen 20
void printList(int *nums, int len) {
int i;
for (i = 0; i < len; i++) {
printf("%d ", nums[i]);
}
}
void merge(int *nums, int start, int mid, int end) {//治
int len=end-start+1;
int * temp=(int *)malloc(sizeof(int)*len);
int k = 0;
int i = start;
int j = mid + 1;
while (i <= mid && j <= end) {//注意区间的连贯性0~mid mid+1~end
if (nums[i] < nums[j]){ //或i=start;j=mid; while(i<mid && j<=end)
temp[k++] = nums[i++];
}
else{
temp[k++] = nums[j++];
}
}
if (i == mid + 1) {
while(j <= end)
temp[k++] = nums[j++];
}
if (j == end + 1) {
while (i <= mid)
temp[k++] = nums[i++];
}
for (j = 0, i = start ; j < k; i++, j++) {
nums[i] = temp[j];
}
free(temp);
temp=NULL;
}
void mergeSort(int *nums, int start, int end) {
#if 0
if (start >= end)
return;
int mid = ( start + end ) / 2;
mergeSort(nums, start, mid);//分 递归划分原数组左半边
mergeSort(nums, mid + 1, end);//递归划分右半边if
merge(nums, start, mid, end);//合并
#endif
if(start<end){
int mid = (start + end)/2;
mergeSort(nums,start,mid);
mergeSort(nums,mid+1,end);
merge(nums,start,mid,end);
}
}
void main(){
int nums[] = {4, 7, 6, 5, 2, 1, 8, 2, 9, 1};
int len=sizeof(nums)/sizeof(int);
mergeSort(nums, 0, len);
printList(nums, len);
}