归并排序定义:
最开始的每个元素单独作为一个子序列,每轮对相邻的子序列两两归并直到归并成一个序列//归并排序的核心思想是将一个大问题分解成若干个小问题,分别解决这些小问题,然后将结果合并起来,最终得到整个问题的解。
1.归并排序的步骤如下:
- 分解(Divide):将待排序的数组分成两个子数组,每个子数组包含大约一半的元素。(分成2份)
- 解决(Conquer):递归or循环每个子数组进行排序。
- 合并(Combine):将两个已排序的子数组合并成一个有序的数组。
2. 算法步骤
申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列;
设定两个指针,最初位置分别为两个已经排序序列的起始位置;
比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置;
重复步骤 3 直到某一指针达到序列尾;
将另一序列剩下的所有元素直接复制到合并序列尾。
第一步:我们需要用一个递归函数来将我们的左边部分和右边部分,分别将每个子序列给拆分为一个元素,(这个可能会有点绕,我们直到递归函数要有终止条件才会跳出循环)
void merge_sort(int arr[], int left, int right) { if (left < right) { int mid = left + (right - left) / 2; merge_sort(arr, left, mid); //这个就是递归的左边的子序列 merge_sort(arr, mid + 1, right); //这个是递归的右边的子序列 merge(arr, left, mid, right); } }里面的merge函数会持续循环调用,单单元素合并,两两元素合并,最后合并2个有序子序列;
下面就是核心 merge核心排序代码
// 简洁版归并排序实现 void merge(int arr[], int left, int mid, int right) {//第一次传的参数是arr,0,0,1就是单独第一个元素嘛,第二次就是 第二个元素和第三个合并, 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 < n2; j++) R[j] = arr[mid + 1 + j]; // 合并 int i = 0, j = 0, k = left; while (i < n1 && j < n2) { if (L[i] <= R[j]) { arr[k++] = L[i++]; //比较大小合并 } else { arr[k++] = R[j++]; } } // 拷贝剩余元素 while (i < n1) arr[k++] = L[i++]; while (j < n2) arr[k++] = R[j++]; // 释放内存 free(L); free(R); }最后就是我们的主函数啦!要测试和调试嘛,在周中学习讲到可能不太精细,周末会提高作品质量,本周末的实战小项目(通讯录管理链表存储)
int main() { int arr[] = {5, 89, 56, 21, 3, 1, 56}; //用于测试我们的代码和调试嘛 int n = sizeof(arr) / sizeof(arr[0]); printf("排序前: "); for (int i = 0; i < n; i++) printf("%d ", arr[i]); printf("\n"); merge_sort(arr, 0, n - 1); printf("排序后: "); for (int i = 0; i < n; i++) printf("%d ", arr[i]); printf("\n"); return 0; }不要忘记!!!malloc函数要引入头文件<stdlib.h>
谢谢大家的观看和学习,有哪些疑问?我们可以相互讨论学习希望我们学者也可以相互学习有一个平台可以帮助大学里面学习的基础c语言免费回答感谢感谢!!!QQ群号:238038904