- 吐吐很快乐
通过【归并排序】学习分治思想~幼儿园的小学生版
- 2025-7-25 14:55:24 @
#include <stdio.h> // 导入打印积木的工具箱
#include <stdlib.h> // 导入其他小工具
// 合并两个有序小队(像拼小火车)
void merge(int arr[], int left, int mid, int right) {
/* 参数说明:
arr:积木大本营
left:左边小队起点
mid:左边小队终点(右边小队起点是mid+1)
right:右边小队终点
*/
// 1. 数清两队积木数量
int n1 = mid - left + 1; // 左边小队积木数量
int n2 = right - mid; // 右边小队积木数量
// 2. 准备两个临时小推车存放积木
int L[n1], R[n2]; // L小车放左边队,R小车放右边队
// 3. 把左边积木搬到L小车(复制过程)
for (int i = 0; i < n1; i++)
L[i] = arr[left + i]; // 从左起点开始搬
// 4. 把右边积木搬到R小车(复制过程)
for (int j = 0; j < n2; j++)
R[j] = arr[mid + 1 + j]; // 从中间点右边开始搬
// 5. 开始拼装小火车(核心比较)
int i = 0; // L小车的指针(看哪块积木)
int j = 0; // R小车的指针
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++; // 大本营位置后移
}
// 6. 处理剩余的积木(当某队搬完了)
while (i < n1) { // 左边小车还有积木
arr[k] = L[i]; // 全部搬到大本营
i++;
k++;
}
while (j < n2) { // 右边小车还有积木
arr[k] = R[j]; // 全部搬到大本营
j++;
k++;
}
// 现在两队积木合并成有序的小火车啦!
}
// 分积木大法(递归分治)
void mergeSort(int arr[], int left, int right) {
/* 参数说明:
arr:积木大本营
left:当前区域的左边界
right:当前区域的右边界
*/
if (left < right) { // 只要积木多于1块就继续分
// 1. 找中间点(把积木堆分成两半)
int mid = left + (right - left) / 2; // 防止数字太大
// 2. 魔法分解(左边分到底)
mergeSort(arr, left, mid); // 处理左边积木堆
// 3. 魔法分解(右边分到底)
mergeSort(arr, mid + 1, right); // 处理右边积木堆
// 4. 拼装小火车(合并已排序的两队)
merge(arr, left, mid, right);
}
// 如果只剩1块积木(left==right),直接返回(天然有序)
}
// 测试积木排序
int main() {
// 准备8块乱序的积木
int arr[] = {9, 5, 1, 4, 3, 2, 7, 6};
int n = sizeof(arr) / sizeof(arr[0]); // 计算积木总数
// 展示原始积木
printf("排序前: ");
for (int i = 0; i < n; i++) printf("%d ", arr[i]);
// 使用魔法分积木大法排序(从0号到7号积木)
mergeSort(arr, 0, n - 1);
// 展示排好队的积木
printf("\n排序后: ");
for (int i = 0; i < n; i++) printf("%d ", arr[i]);
return 0; // 游戏结束
}
排序前: 9 5 1 4 3 2 7 6 排序后: 1 2 3 4 5 6 7 9 分积木步骤图解 假设积木 [9,5,1,4]:
第一刀:切成 [9,5] 和 [1,4]
再切左边:[9] 和 [5] → 合并成 [5,9]
再切右边:[1] 和 [4] → 合并成 [1,4]
最后合并:比较 [5,9] 和 [1,4] 的最前面:
1<5 → 放1
4<5 → 放4
放5 → 放9
结果:[1,4,5,9]
就像把混乱的积木不断对半拆分,最后把排好序的小块像拼火车一样连接起来!
2 条评论
-
13707661150 我不要标枪 LV 6 @ 2025-7-25 15:02:05
给肚子里的小宝宝解释的代码
亲爱的宝宝,这是一段用积木来教你排序的魔法代码哦!我来用你能听懂的话解释:
c #include <stdio.h> // 这是妈妈用来打印积木排列的工具箱 #include <stdlib.h> // 这是爸爸用来帮忙的其他小工具
// 把两队已经排好队的小积木合并成一队 void merge(int arr[], int left, int mid, int right) { // 左边小队有这么多积木 int n1 = mid - left + 1; // 右边小队有这么多积木 int n2 = right - mid;
// 准备两个小篮子装积木 int L[n1], R[n2]; // 把左边积木放进左边篮子 for (int i = 0; i < n1; i++) L[i] = arr[left + i]; // 把右边积木放进右边篮子 for (int j = 0; j < n2; j++) R[j] = arr[mid + 1 + j]; // 开始排队啦! int i = 0; // 左边篮子的积木指针 int 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++; }
}
// 把一堆乱糟糟的积木排好队 void mergeSort(int arr[], int left, int right) { if (left < right) { // 把积木堆分成两半 int mid = left + (right - left) / 2;
// 让左边的积木排好队 mergeSort(arr, left, mid); // 让右边的积木排好队 mergeSort(arr, mid + 1, right); // 把两队排好队的积木合并成一队 merge(arr, left, mid, right); }
}
// 我们来玩积木排队游戏吧! int main() { // 这里有8块乱糟糟的积木 int arr[] = {9, 5, 1, 4, 3, 2, 7, 6}; int n = sizeof(arr) / sizeof(arr[0]);
// 看看积木原来是怎么排的 printf("排队前: "); for (int i = 0; i < n; i++) printf("%d ", arr[i]); // 用魔法让积木排好队 mergeSort(arr, 0, n - 1); // 看看积木现在排得多整齐 printf("\n排队后: "); for (int i = 0; i < n; i++) printf("%d ", arr[i]); return 0; // 游戏结束啦
}
-
2025-7-25 14:56:57@
goood
- 1