今天写一个归并排序的模板,返回值为该序列的逆序对数

基本思路

归并排序就是利用二分的思想,将区间无限递归二分,直到当前划分区间只包含一个元素或没有元素的时候(我们认为这个序列是自动有序的),我们回溯到上一层,然后将当前层的左右两个区间合并为一个有序序列,然后继续回溯,回溯之后,当前层的左右两个区间都应该分别是已经经过合并的有序子区间,我们将这两个有序子区间再进行有序合并,再返回上一层,直到返回最大区间,则合并最大区间的左右有序子区间,得到有序序列。

流程演示

比如:22  3  1  5  4  7  9  1  8  0

红色区间划分:22  3  1  5  4

左边:   3       右边     5   4

左边:合并有序:3   22

右边:5  4区间递归返回时候变为:4 5

右边合并:1  4  5

左右区间合并为一个区间:1  3  4  5  22

至此左侧区间处理完毕

右侧区间同理,得到有序序列:0  1  7  8  9

最后合并整个区间

0  1  1  3  4  5  7  8  9  22

逆序对数

我们利用归并的思想,它会将每个区间细分到最小,返回整合的时候,会进行左右区间合并,合并的时候就要比较左右区间当前值那个大,然后取小的那个,我们可以在比较的时候做记录,如果左侧的值小于右侧,我们就做记录,这样一路回溯,就会找到所有的逆序对数。

我们利用归并排序的返回值来将此记录值输出到外部

泛型代码:

template<typename value_type, typename value_Ptr>
int merge_sort(const value_Ptr& begin, const value_Ptr& end)
{
static std::vector<value_type> to(end - begin);
static int cnt{ }; //记录逆序对数
if (end - begin <= )return ; value_Ptr mid = begin + (end - begin) / ; merge_sort<value_type>(begin, mid);
merge_sort<value_type>(mid, end); //将上述两段区间顺序排列
value_Ptr l = begin, r = mid;
int k{ }, index{ }; while (l < mid && r < end)
if (*l < *r)to[k++] = *l++;
else //如果左侧值小于右侧
{
cnt += mid - l; //逆序对数记录
to[k++] = *r++;
} while (l < mid)to[k++] = *l++;
while (r < end)to[k++] = *r++; for (index = ; begin + index < end; ++index)*(begin + index) = to[index]; return cnt;
}

测试与使用

#include <iostream>
#include <vector> using namespace std; int main()
{
ios::sync_with_stdio(false);
int list[]{ ,,,,,,,,, };
vector<int> v{ list,list + }; int cnt = merge_sort<int>(list + , list + );
merge_sort<int>(v.begin(), v.end());
for (auto it : v)cout << it << " ";
cout << endl;
for (auto it : list)cout << it << " ";
cout << endl;
cout << "逆序对数:" << cnt << endl << endl; char list_[]{ 'r','c','','A','z','b','','','r', '' };
vector<char>v_{ list_,list_ + }; cnt = merge_sort<char>(list_ + , list_ + );
merge_sort<char>(v_.begin(), v_.end());
for (auto it : v_)cout << it << " ";
cout << endl;
for (auto it : list_)cout << it << " ";
cout << endl;
cout << "逆序对数:" << cnt << endl << endl;
}

时间复杂度为:O(N * log N)

感谢您的阅读,生活愉快~

最新文章

  1. 菜鸟学Linux命令:nohup命令启动程序
  2. GitHub 操作流程示例
  3. java jvm学习笔记三(class文件检验器)
  4. HW2.16
  5. CentOS 5.6服务器配置YUM安装Apache+php+Mysql+phpmyadmin
  6. 转载:10 Easy Steps to a Complete Understanding of SQL
  7. Windbg调试命令详解(1)
  8. PHP移动互联网开发笔记(2)——变量及常量
  9. 设置Cookie,登录记住用户登录信息,获取用户登录过得信息
  10. LeetCode OJ 153. Find Minimum in Rotated Sorted Array
  11. LeetCode 88. Merge Sorted Array(合并有序数组)
  12. Python开发工具PyCharm个性化设置
  13. [Lugu3380]【模板】二逼平衡树(树套树)
  14. 《JavaScript高级程序设计》笔记:客户端检测(九)
  15. Linux 学习 (三) 文件搜索命令
  16. sqlite比较时间起始1天的0点
  17. xml文档对象模型doc
  18. django2.1---admin 修改模块的名字为中文显示
  19. PyTorch-Kaldi 语音识别工具包
  20. arduino 配置 esp8266

热门文章

  1. C语言编写守护进程
  2. sqlalchemy操作数据库(二)
  3. http Get和Post请求方式
  4. Android手动回收bitmap,引发Canvas: trying to use a recycled bitmap处理
  5. nginx 的多域名多https转发设置方法【转】
  6. 26 About the go command go命令行
  7. Mac上删除不了的文件,Windows上也粉碎不了怎么办?
  8. 正则表达式之你不知道的replace
  9. docker容器配置独立ip
  10. Linux入门(一)root密码设置和用户切换