<泛> 归并排序 及 逆序对

时间:2022-09-20 21:37:53

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

基本思路

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

流程演示

比如: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. 2014 HDU多校弟五场A题 【归并排序求逆序对】

    这题是2Y,第一次WA贡献给了没有long long 的答案QAQ 题意不难理解,解题方法不难. 先用归并排序求出原串中逆序对的个数然后拿来减去k即可,如果答案小于0,则取0 学习了归并排序求逆序对的 ...

  2. hihoCoder&lowbar;二分&amp&semi;&num;183&semi;归并排序之逆序对

    一.题目 题目1 : 二分·归并排序之逆序对 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描写叙述 在上一回.上上回以及上上上回里我们知道Nettle在玩<艦これ&g ...

  3. 归并排序&amp&semi;&amp&semi;归并排序求逆序对

    归并排序 归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用.将已有序的子序列合并,得到完全有序的序 ...

  4. 【BZOJ4769】超级贞鱼 归并排序求逆序对

    [BZOJ4769]超级贞鱼 Description 马达加斯加贞鱼是一种神奇的双脚贞鱼,它们把自己的智慧写在脚上——每只贞鱼的左脚和右脚上各有一个数.有一天,K只贞鱼兴致来潮,排成一列,从左到右第i ...

  5. POJ-排序-归并排序与逆序对

    排序:归并排序与逆序对 一.概念 归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用.将已有序的子序 ...

  6. poj2299&lpar;归并排序求逆序对&rpar;

    题目链接:https://vjudge.net/problem/POJ-2299 题意:给定一个序列,每次只能交换邻近的两个元素,问要交换多少次才能使序列按升序排列. 思路:本质就是求逆序对.我们用归 ...

  7. 归并排序&plus;归并排序求逆序对(例题P1908)

    归并排序(merge sort) 顾名思义,这是一种排序算法,时间复杂度为O(nlogn),时间复杂度上和快排一样 归并排序是分治思想的应用,我们先将n个数不断地二分,最后得到n个长度为1的区间,显然 ...

  8. 归并排序求逆序对&lpar;poj 2299&rpar;

    归并排序求逆序对 题目大意 给你多个序列,让你求出每个序列中逆序对的数量. 输入:每组数据以一个数 n 开头,以下n行,每行一个数字,代表这个序列: 输出:对于输出对应该组数据的逆序对的数量: 顺便在 ...

  9. HDU 3743 Frosh Week&lpar;归并排序求逆序对&rpar;

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3743 题目意思就是给你一个长为n的序列,让你求逆序对.我用的是归并排序来求的.归并排序有一个合并的过程 ...

随机推荐

  1. ASIFormDataRequest实现post的代码示例

    用jquery实现的Post方法可能如下 var param = $.param({ data: JSON.stringify({"from":"234",&q ...

  2. php数据类型有哪些&quest;

    php数据类型有哪些?有三大类1.基本数据类型 1.1整型 $a = 0123; // 八进制数(是以0开头) 83 $a = 0x1A; // 十六进制数              26 1.2小数 ...

  3. geometry(简单数学题)

    geometry  Accepts: 324  Submissions: 622  Time Limit: 2000/1000 MS (Java/Others)  Memory Limit: 6553 ...

  4. 中国气象台api

    1. XML接口 http://flash.weather.com.cn/wmaps/xml/china.xml 这个是全国天气的根节点,列出所有的省,其中的pyName字段是各个省XML的文件名,比 ...

  5. 201521123057 《Java程序设计》第9周学习总结

    1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结异常相关内容. 2. 书面作业 常用异常 1.题目5-1 1.1 截图你的提交结果(出现学号) 答: 1.2 自己以前编写的代码中经 ...

  6. 【ASP&period;NET MVC 学习笔记】- 04 依赖注入(DI)

    本文参考:http://www.cnblogs.com/willick/p/3223042.html 1.在一个类内部,不通过创建对象的实例而能够获得某个实现了公开接口的对象的引用.这种"需 ...

  7. Python学习&lowbar;08&lowbar;函数式编程

    在python中,函数名也是一个变量,代表对一个函数内容的引用,意味着可以作为参数传入到其他函数中,根据这个特性,发散出装饰器.闭包等概念,并涉及到变量作用域等问题. 函数 python中函数操作符为 ...

  8. FP-growth算法思想和其python实现

    第十二章 使用FP-growth算法高效的发现频繁项集 一.导语 FP-growth算法是用于发现频繁项集的算法,它不能够用于发现关联规则.FP-growth算法的特殊之处在于它是通过构建一棵Fp树, ...

  9. 洛谷P1983车站分级题解

    题目 这个题非常毒瘤,只要还是体现在其思维难度上,因为要停留的车站的等级一定要大于不停留的车站的等级,因此我们可以从不停留的车站向停留的车站进行连边,然后从入度为0的点即不停留的点全都入队,然后拓扑排 ...

  10. C&num; 单元测试(入门)

    注:本文示例环境 VS2017XUnit 2.2.0 单元测试框架xunit.runner.visualstudio 2.2.0 测试运行工具Moq 4.7.10 模拟框架 什么是单元测试? 确保软件 ...