归并排序基础代码注释讲解
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
void merge(int arr[], int left, int mid, int right) {
//n1 n2 只是两个标签,用来表示左右两个子数组的长度
int n1 = mid - left + 1;
int n2 = right - mid;
//动态开两个子数组的对应的内存空间
int* L = (int*)malloc(n1 * sizeof(int));
int* R = (int*)malloc(n2 * sizeof(int));
//把大数组拆开成两个子数组并且把值分开存到子数组里面
//左子数组
for (int i = 0; i < n1; i++) {
L[i] = arr[left + i];
}
//右子数组
for (int j = 0; j < n1; j++) {
R[j] = arr[mid + 1 + j];
}
//建立效指针变量,用来指定
int i = 0, j = 0; //两个子数组箭标
int k = left; //临时数组的效指针变量,但是这个代码是直接原地更改
//进入循环的条件:两个数组都没有遍历完,要都还有元素
//限制:两个子数组要是有序的,也正因此才用递归递进到基准条件才进行调用
while (i < n1 && j < n2) {
//两个数组左右依次比较排空掉内部元素,把较小的那个放到临时数组里面
if (L[i] <= R[j]) {
arr[k] = L[i];
i++; //哪个子数组被放拿走元素放到临时数组里面了自然要移动它的指针
} else {
arr[k] = R[j];
j++; //哪个子数组被放拿走元素放到临时数组里面了自然要移动它的指针
}
k++; //一次操作之后,临时数组里面也有了一个元素,效指针变量要移动一下
}
//检查左子数组是否剩余
while (i < n1) {
arr[k] = L[i];
i++;
k++;
}
//检查右子数组是否剩余
while (j < n2) {
arr[k] = R[j];
j++;
k++;
}
free(L);
free(R);
}
//排序的实现,利用递归分而治之的思想
void sort(int arr[], int left, int right) {
if (left < right) {
int mid = left + (right - left) / 2;
sort(arr, left, mid); //mid = 0时候,left = 0, right = 1, mid = 0
sort(arr, mid + 1, right); //mid = 0时候,无意
merge(arr, left, mid, right); //mid = 0时候正式开始归并排序
}
}
int main() {
system("chcp 65001");
int num[] = {6, 4, 3, 2, 9, 8, 1, 4};
int n = sizeof(num) / sizeof(num[0]);
sort(num, 0, n - 1);
for (int i = 0; i < n; i++) {
printf("%d ", num[i]);
}
return 0;
}