SHUOJ——归并排序——计算思维J题
2015-09-02 13:04
288 查看
归并排序(Mergesort)
归并排序以O(NlogN)的复杂度运行,是使用比较次数最优解以及基于递归算法的很好的实例。算法原理:
算法的基本操作是合并两个已经排序的表,然后按顺序将两个表中的元素进行比较厚放入第三个表中。 基本的合并算法是取两个输入数组A和B,一个输出数组C,以及三个指针pA,pB,pC. 他们都始于对应数组的开始端。 A[pA]和B[pb]中的较小者放入C的下一个位置,pc以及较小者的指针向前推进一格。 当有其中一格输入表输完时,则将另外一个输入表剩余元素输入到输出表的位置中。
显然,合并两个已经排序的表是线性的,因为最多只能进行N-1次比较(N为元素总数)。 注意点:每次比较都只放一个元素,但最后一次比较完是放两个元素
因此归并排序很容易描述为递归操作。如果N=1 ,则只需要一格元素排序,否则,就以递归的方式将前半部分和后半部分各自排序。
复杂度分析:
我们以N=1时的操作数视为常数1,并且假定N为2的幂整数。那么我们总能将N分成均为偶数的两个部分。另外,对N个数排序的用时等于完成两个大小为N/2的递归排序所用的时间再加上合并的时间(即当前元素总数)
那么我们可以得到:
T(1)=1
T(N)=2T(N/2)+N
我们在2式两边除以N 则能得 T(N)/N=T (N/2)/ N/2 + 1
同样的,因为N是2的幂整数,我们可以将N一直往下除2变成:
T(N)=2T(N/2)+N
T(N/2) / N/2 = T( N/ 4) / N/4 + 1
T( N/4) / N/4 =T (N/8) / N/8 + 1
………………
T(2)/ 2 = T(1) / 1 +1
我们将上式相加,左右相同元素消去,最终得到:
T(N) / N = T(1 ) /1 +log N
最终得到 T(N)= N log N +N = O(N log N)
现在贴例题: http://202.121.199.212/JudgeOnline/problem.php?cid=1130&pid=9
Description
Sort公司是一个专门为人们提供排序服务的公司,该公司的宗旨是:“顺序是最美丽的”。他们的工作是通过一系列移动,将某些物品按顺序摆好。他们的服务是通过工作量来计算的,即移动东西的次数。所以,在工作前必须先考察工作量,以便向用户提出收费数目。假设我们将序列中第i件物品的参数定义为Ai,那么,排序就是指将A数组从小到大排序。用户并不需要知道精确的移动次数,实质上,大多数人都是凭感觉来认定这一列物品的混乱程度,根据Sort公司的经验,人们一般是根据“逆序对”的数目多少来称呼这一序列的混乱程度。
若数组A的元素A1,…,An互不相同,所谓数组A的“逆序对”是指,若i<j且Ai>Aj,则<i,j>就为一个“逆序对”。请你为Sort公司做一个程序,在尽量短的时间内,统计出"逆序对"的数目。
Input
输入有若干行,每两行对应一种情形。两行中的第一行为一个整数n(1≤n≤1000),接下来一行为n个互不相同的整数。输入直到文件输入结束。
Output
对每一种情形的测试数据,在一行上先输出“Case #:”,其中“#”是测试数据集的编号(从1开始),接着在下面的输出结果。Sample Input
5
3 1 4 5 2
6
1 2 3 4 5 6
7
7 6 5 4 3 2 1
Sample Output
Case 1:
4
Case 2
:0
Case 3:
21
题目思路 : 通过归并算法,以分支 递归 将数组分为前后两个部分, 当前半部分数组元素大于后半部分数组元素时,则说明需要进行比较的替换,
其比较次数 ans =m -i +1 (其中 m为数组中间位置, i为前半部分数组需要进行交换的元素的位置, ans原理不证)
贴代码:
#include <iostream> #include <string.h> #include <stdio.h> #ifndef _SHUOJ_J_ #define _SHUOJ_J_ using namespace std; const int Maxn = 1005; int a[Maxn],tmp[Maxn]; int ans; void Merge(int l,int m,int r) { int i = l; int j = m + 1; int k = l; while(i <= m && j <= r) { if(a[i] > a[j]) //进行比较 { tmp[k++] = a[j++]; //大于则说明需要交换 ans += m - i + 1; } else { tmp[k++] = a[i++]; //小于直接放入输出数组 } } while(i <= m) tmp[k++] = a[i++]; //此时有一表已经输完,将剩余元素放入表中 while(j <= r) tmp[k++] = a[j++]; for(int i=l;i<=r;i++) a[i] = tmp[i]; //将排序好的数组放入 } void Merge_sort(int l,int r) { if(l < r) { int m = (l + r) >> 1; Merge_sort(l,m); Merge_sort(m+1,r); Merge(l,m,r); } } int main() { int n,tt=1; int cas=0; while(cin>>n) { cas++; for(int i=0;i<n;i++) cin>>a[i]; ans = 0; Merge_sort(0,n-1); printf("Case %d:\n",cas); cout<<ans<<endl; } return 0; } #endif //SHUOJ_J_
相关文章推荐
- OAF学习笔记-16-自定义异常的抛出
- OAF学习笔记-16-自定义异常的抛出
- 自动化脚本自动生成技术探讨
- mybatis 详细入门例子
- Myeclipse 10 使用之修改字体
- 写在前面的话
- OAF学习笔记-16-自定义异常的抛出
- OAF学习笔记-16-自定义异常的抛出
- OAF学习笔记-16-自定义异常的抛出
- OAF学习笔记-16-自定义异常的抛出
- OAF学习笔记-16-自定义异常的抛出
- OAF学习笔记-16-自定义异常的抛出
- OAF学习笔记-16-自定义异常的抛出
- OAF学习笔记-16-自定义异常的抛出
- OAF学习笔记-16-自定义异常的抛出
- OAF学习笔记-16-自定义异常的抛出
- OAF学习笔记-16-自定义异常的抛出
- 451 光棍节的快乐【错排公式】
- POJ 3735 Training little cats(矩阵快速幂)
- 黑马程序员-------Java基础-------集合