合并排序 分治(递归、自然合并排序)实现(C++)
2020-06-01 05:12
1046 查看
文章目录
一、合并排序(归并排序)概念
定义:
引用自"百度百科"
·
- 合并排序是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。
- 合并排序法是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个子序列,每个子序列是有序的。然后再把有序子序列合并为整体有序序列。
- 将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为2-路归并。合并排序也叫归并排序。
算法步骤:
引用自"菜鸟教程"
- 申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列;
- 设定两个指针,最初位置分别为两个已经排序序列的起始位置;
- 比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置;
- 重复步骤 3 直到某一指针达到序列尾;
- 将另一序列剩下的所有元素直接复制到合并序列尾。
二、分治&递归算法实现
1. 设计递归方程
- 我们需要将序列拆分,将当前区间一分为二,即求中间点
- 递归地对两个子区间 L[left…mid] 和 R[mid+1…right] 进行归并排序
/ / 3. 将已排序的两个子区间 L[left…mid] 和 R[mid+1…right] 合并为一个有序的区间[left…right]
2. 确定边界条件
- 当拆分后的子序列只含有一个元素时,结束递归调用,开始合并操作。
3. 编写程序代码
// 合并排序 #include<iostream> using namespace std; void mergeSort(int array[], int left, int right); void merge(int array[], int left, int mid, int right); int main() { // 待排序数组,也可进行改写,获取键盘输入进行排序 int array[] = { 10,5,8,6,3,9,4,1,2,7 }; int len = sizeof(array) / sizeof(int); // 数组长度 mergeSort(array, 0, len-1); cout << "合并排序:"; for (int i = 0;i < len;i++) cout << array[i] << " "; cout << endl; return 0; } void mergeSort(int array[], int left, int right) { // 当子序列就只有一个元素的时候结束递归调用 if (left == right) return; else { // 分治 // 判断中间位置,进行拆分 int mid = (left + right) / 2; mergeSort(array, left, mid); mergeSort(array, mid + 1, right); // 合并 merge(array, left, mid, right); } } void merge(int array[], int left, int mid, int right) { // 声明一个指针,指向临时数组,临时存放排序后的元素 int* tempArray = new int[right - left + 1]; int left_1 = left; // 指向 左待排序区域 第一个元素 int left_2 = mid + 1; // 指向 右待排序区域 第一个元素 int k = 0; // 指向 临时数组 第一个元素 // 顺序选取两个待排序区的较小元素,存储到tempArr数组中 while (left_1 <= mid && left_2 <= right) { // 将较小的元素存入tempArr数组中,并将指针递增 if (array[left_1] <= array[left_2]) tempArray[k++] = array[left_1++]; else tempArray[k++] = array[left_2++]; } // 若比较完之后,有序区仍有剩余元素,则直接复制到tempArray数组中 while (left_1 <= mid) tempArray[k++] = array[left_1++]; while (left_2 <= right) tempArray[k++] = array[left_2++]; // 将临时数组中排序后的元素取出 for (int i = left, j = 0;i <= right;i++,j++) array[i] = tempArray[j]; // 删除指针 delete[] tempArray; }
4. 运行结果展示
三、自然合并排序
1. 描述&基本思想
- 自然合并排序是合并排序算法的一种改进
- 对于初始给定的数组,通常存在多个长度大于1的已排好序的子数组段。因此用一次线性扫描就可以找出所有这些排好序的子数组段,然后将相邻的排好序的子数组段两两合并
- 注:通常情况下, 按此方式进行合并排序所需的合并次数较少。
- 举个栗子: 数组a中元素为{2, 5, 8, 3, 6, 10, 4, 9};
- 用一次对数组a的线性扫描,找出自然排好序的子数组段:{2, 5, 8},{3, 6},{10},{4, 9};
- 然后将相邻的排好序的子数组段两两合并:{2, 3, 5, 6, 8},{4, 9, 10};
- 继续合并直至整个数组排好序{2, 3, 4, 5, 6, 8, 9, 10}。
2. 编写程序代码
// 待更新。。。
3. 运行结果展示
运行截图(待更新。。。)
*其它一些常见算法请参阅此链接~
最后,非常欢迎大家来讨论指正哦!
相关文章推荐
- 【算法设计】合并排序、自然合并排序与快速排序算法的Java实现
- 数据结构--排序之归并排序(分治 递归 合并典型案例)
- 递归与分治-合并排序、快速排序以及循环赛问题
- 合并两个排序链表--迭代和递归分别实现
- 剑指Offer 面试题25:合并两个排序的链表(递归+非递归) Java代码实现
- 合并两个已排序的链表(递归方法实现)
- Ackerman函数的递归、全排列的递归实现、整数划分的递归、二分搜索的递归、合并排序的递归、.快速排序
- 合并排序三-算法导论递归实现
- Java语言描述:递归与分治策略之合并排序与快速排序
- 合并排序的递归实现算法
- 算法设计与分析 合并排序的递归实现算法
- 快速排序的递归实现。 分治法。
- 分治:合并排序的java程序实现
- 递归实现合并排序
- 合并两个排序的链表---递归实现
- [算法简结]递归分治(二):合并排序
- java实现合并两排序链表
- JAVA实现合并两个排序的链表(《剑指offer》)
- element-ui表格拖曳标题分组合并排序组件的实现
- 无聊写排序之 ---- 快速排序(QuickSort) 递归实现