MergeSort归并排序递归、迭代、原地 c++实现
来源:互联网 发布:oracl 显示所有数据库 编辑:程序博客网 时间:2024/06/05 09:39
分治(Divide and Conquer)的思想,平均、最好、最坏,时间效率都是O(n log n)。
有递归和迭代两种实现方法。对于顺序存储如数组,一般为O(n)的空间;list的空间直接为O(1)。
空间上可以使用原地归并避免O(n)的空间。但较麻烦,且需要多次移动,除非有特殊说明或空间非常宝贵,否则不建议原地归并。
void merge_sort(vector<int>& arr){ if(arr.empty()) return; vector<int> ans(arr.size()); merge_sort_re(arr, ans, 0, arr.size());//1.递归 //merge_sort_it(arr, arr.size());//2.迭代}
1.递归
void merge_sort_re(vector<int>& arr, vector<int>& ans, int beg, int end){ if(end - beg <= 1)return; int mid = beg + (end-beg)/2; merge_sort_re(arr, ans, beg, mid); merge_sort_re(arr, ans, mid, end); merge(arr, ans, beg, end);//a.归并, O(n)的空间 //merge_inplace(arr, beg, end);//b.原地归并, O(1)的空间}
a.归并, O(n)的空间
void merge(vector<int>& arr, vector<int>& ans, int beg, int end){ int mid = beg + (end-beg)/2; int i = beg, j = mid, k = beg; while(i<mid && j<end) ans[k++] = arr[i]>arr[j] ? arr[j++] : arr[i++]; while(i<mid) ans[k++] = arr[i++]; while(j<end) ans[k++] = arr[j++]; for(k = beg; k<end; ++k) arr[k] = ans[k];}
b. 原地归并, O(1)的空间
merge_inplace(arr, beg, end),归并[beg,end)范围内的数。其中,[beg,mid)、[mid,end)分别有序。
算法流程:
(0)变量i、j初值分别为beg、mid = beg + (end-beg)/2。
(1)首先自增i,在arr前半部找到第一个比arr[j]大的数,为arr[i];
中间变量k保存此时j的值;
(2)然后自增j,在arr后半部找到第一个比arr[i]大的数,为arr[j];
(3)此时,arr[i]前的数不需要处理;arr[x] (x的范围为[i,k) )中的全部数(记为A_x)大于arr[y](y的范围为[k,j) )中的全部数(记为A_y);记移动前,t = arr[j],现在只需要通过 move(arr, i, k, j) 将A_y 中的全部数移至A_x中的全部数前,即可保证arr在[beg, end)范围内,移动后数t所在的位置之前(不包括数t所在的位置)的全部数都有序;
(3)更新i的值为移动后arr[i]所在位置,即i自增区间[k,j)的长度 i+=j-k,重新执行(1)~(3),直到i、j满足循环退出条件。
时间分析:最坏O(n^2),因此除非有特殊说明或空间非常宝贵,否则不建议原地归并。
//将arr中[k,j)范围内的数移至[i,k)范围前void move(vector<int>& arr, int i, int k, int j){ reverse(arr.begin()+i, arr.begin()+k); reverse(arr.begin()+k, arr.begin()+j); reverse(arr.begin()+i, arr.begin()+j);}//原地归并, O(1)的空间void merge_inplace(vector<int>& arr, int beg, int end){ int mid = beg + (end-beg)/2; int i = beg, j = mid; while(i<j && j<end){ int k = j; while(i<j && arr[i]<=arr[j]) ++i; while(j<end && arr[j]<=arr[i]) ++j; move(arr, i, k, j); i+=j-k; }}
reference: blog
2.迭代
void merge_sort_it(vector<int>& arr, int len){ vector<int> ans(len); for(int seg = 1; seg < len; seg+=seg){ for(int beg = 0; beg < len; beg+=seg+seg){ int low = beg, mid = std::min(beg+seg, len), high = std::min(beg+seg+seg, len); int i = low, j = mid, k = low; while(i<mid && j < high) ans[k++] = arr[i]>arr[j] ? arr[j++] : arr[i++]; while(i<mid) ans[k++] = arr[i++]; while(j<high) ans[k++] = arr[j++]; for(k = beg; k < high; ++k) arr[k] = ans[k]; } }}
reference: wiki
- MergeSort归并排序递归、迭代、原地 c++实现
- 归并排序(mergeSort)之递归实现
- 归并排序 MergeSort C语言实现
- 归并排序C语言实现MergeSort
- 无聊写排序之 ---- 归并排序(MergeSort) 递归实现
- 无聊写排序之 ---- 归并排序(MergeSort) 非递归实现
- C++实现归并排序Mergesort(使用递归的方法)
- 实现归并排序MergeSort的非递归动画演示
- 归并排序(递归实现和迭代实现)
- MergeSort -- 归并排序(C++)
- 归并排序的迭代及递归实现
- linux下归并排序(MergeSort)算法的C语言实现
- 【归并排序(非递归)】MergeSort(non-recursion)
- 非递归的归并排序(MergeSort)
- 归并排序(mergeSort)之非递归算法
- Java排序算法(三)--归并排序(MergeSort)递归与非递归的实现
- 面试之路(16)-归并排序详解(MergeSort)递归和非递归实现
- MergeSort-归并排序(C++实现)
- 我的CUDA学习之旅4——Sobel算子图像边缘检测CUDA实现
- 利用grafana监控网站访问延时率
- Android电池
- html部分(包括浏览器的兼容)知识总结
- 配置 SQL Server Email 发送以及 Job 的 Notification通知功能
- MergeSort归并排序递归、迭代、原地 c++实现
- windows下串口的设置问题
- viewpager与radiogroup结合
- 第30节:查看selenium API
- js删除字符串的最后一个字符三种方法
- crtmpserver流媒体服务器的介绍与搭建
- JS实现60s倒计时(亲测有效),及span标签如何使用和禁用onclick事件
- String:344. Reverse String
- java复习-异常+断言