分治法之归并排序
来源:互联网 发布:淘宝cad画图接活群 编辑:程序博客网 时间:2024/05/21 01:58
分治法之归并排序
目录
- 分治法之归并排序
- 目录
- 摘要
- 分治法的步骤
- 主方法The master method
- 主方法的实例
- 归并排序
- 归并排序的实例1
- 归并排序的实例2
- 思路分析
- aha
摘要
本小节中主要讨论分治法
在归并排序
的应用:
- 分治法的步骤
- 主方法
- 归并排序的算法
- 归并排序的实例
分治法的步骤
Divide the problem into one or more subproblem
- 分解:将原问题划分为一些子问题,子问题的形式和原问题的相同,但是规模减小
Conquer the subproblems by solving them recursively.
- 解决:利用递归求解出子问题的解,如果子问题的规模足够小,则停止递归,直接求解
Combine the solutions to the subproblems into the solution for the original problem
- 合并:将子问题的解合并成原问题的解 -
主方法(The master method)
Master theorem 是判断递归式,求解估算算法复杂度比较常用的方法,它的主要内容如下:
Master theorem (reprise)
T(n) = aT(n/b) + f(n)
CASE 1: f(n) = O(n log b a – ε ), constant ε > 0
⇒ T(n) = Θ(n log b a ) .
CASE 2: f(n) = Θ(n log b a lg k n), constant k ≥ 0
⇒ T(n) = Θ(n log b a lg k+1 n) .
CASE 3: f(n) = Ω(n log b a + ε ), constant ε > 0,
and regularity condition
⇒ T(n) = Θ(f(n)) .
主方法的实例
eg1 : T(n)=4T(n/2)+n
由于f(n)=n=O(n^2),属于CASE1,==>T(n)=Θ(n^2)
eg2 : T(n)=2T(n/2)+n
由于f(n)=n=Θ(n^2),属于CASE2,==>T(n)=Θ(nlgn)
eg3 : T(n)=4T(n/2)+n^3
由于f(n)=n^3=Ω(n^2),属于CASE3,==>T(n)=Θ(n^3)
归并排序
merge算法伪代码1 :
Merge算法伪代码2 :
Merge(B[0...p-1],C[0...q-1],A[0,p+q-1])//将两个有序数组合并成一个有序数组//输入:两个有序数组B[0...p-1],C[0...q-1]//输出:A[0,p+q-1]中已经有序存放了B和C的元素 i<-0;j<-0;k<-0; while i<p && j<q do if B[i]<=C[j] A[k] <- B[i];i <- i+1 else A[k] <- C[j];j <- j+1 k <- k+1 if i=p copyC[j...q-1] to A[k..p+q-1] else copyB[i...p-1] to A[k..p+q-1]
MergeSort算法伪代码1 :
MergeSort算法伪代码2 :
MergeSort(A[0,n-1])//递归调用mergesort对数组A进行排序//输入:一个可排序数组A[0...n-1]//输出:非降序排列的数组A[0,n-1]if n>1 copy a[0...n/2] to B[0...n/2] copy a[n/2+1...n-1] to C[0...n/2]MergeSort(B[0...n/2])MergeSort(C[0...n/2])Merge(B,C,A)
MergeSort 的例子 :
归并排序的实例1
eg : 应用归并算法将序列EXAMPLE按照字母表顺序排序
/** 归并排序:C 语言** @author Erice_s* @date 2017/10/13** 参数说明:* a -- 一个可排序的数组* first -- 第一个有序数组下标最小的数* last -- 第二个有序数组下标最大的数* mid -- 第一个有序数组结束,第二个有序数组开始的下标*/#include <stdio.h>#include <stdlib.h>#include <string.h>void merge(char *a, int first, int mid, int last){ int i = first; int j = mid + 1; int m = 0; char *ptmp = (char*)malloc((last - first + 1)*sizeof(char)); while (i <= mid&&j <= last) { if ((int)a[i] < (int)a[j]) ptmp[m++] = a[i++]; else ptmp[m++] = a[j++]; } while (i <= mid) ptmp[m++] = a[i++]; while (j<=last) ptmp[m++] = a[j++]; for (i = 0; i < last - first + 1; i++) a[first+i] = ptmp[i]; free(ptmp);}void mergeSort(char *a, int first, int last){ if (a==NULL||first >= last) return; int mid = (first & last) +((first^last) >> 1); //int mid = (first + last)/2;//may cause overflow mergeSort(a, first, mid); mergeSort(a, mid+1, last); merge(a,first,mid,last);}void print(char *p,int len){ for (int i = 0; i < len; i++) { printf("%c", p[i]); } printf("\n");}int main(void){ char p[] = { 'E','X','A','M','P','L','E' }; int len = sizeof(p)/sizeof(*p); printf("mergeSort before: "); print(p, len); mergeSort(p, 0, len-1); printf("mergeSort after: "); print(p, len); system("pause"); return 0;}
运行结果 :
归并排序的实例2
eg 2 :有N个整数,A[1]…A[N],需要找到这样的(i,j)的数对d的数量;满足要求:
1 <= i < j<= N && A[i]>A[j]
数据范围:1<=N<=65537 , 0< A[i] <10^9
算法时间复杂度为O(nlgn)
思路分析:
采用归并排序的思想,先把问题的规模变小,问题可以简化为三个子问题,解决A[]左边存在多少逆序对,A[]右边存在多少逆序对,横跨mid的有多少逆序对。
/** 归并排序:C 语言** @author Erice_s* @date 2017/10/13** 参数说明:* a -- 一个可排序的数组* l -- 左边界* m -- 中值* r -- 右边界*/#define _CRT_SECURE_NO_WARNINGS#include <iostream>#include <cstdio>using namespace std;#define MAXN 65537int a[MAXN];int la[MAXN], ra[MAXN];long long cnt; // 逆序对数目void merge (int l, int m, int r) //l 左边界,m 中值 , r 右边界{ int p1 = 0, p2 = 0, j, k; for ( int i = l ; i <= m; i++) la[p1++] = a[i]; // 初始化 la 数组 for (int i = m+ 1; i <= r; i++) ra[p2++] = a[i]; // 初始化 ra 数组 la[p1] = ra[p2] = 0x3f3f3f3f; j = k = 0; for (int i = l; i <= r; i++) { if (la[j] <= ra[k]) a[i] = la[j++]; else { a[i] = ra[k++]; cnt += p1 -j; } }}void mergeSort( int l, int r){ if (l >= r) return; int m = (l & r) +((l ^ r)>> 1); mergeSort(l, m); mergeSort(m + 1, r); merge(l, m, r);}int main(){ int n; while (~scanf("%d", &n)) { cnt = 0; for (int i = 0; i < n; i++) scanf("%d", &a[i]); mergeSort(0, n -1); printf("测试数组的元素个数: %d\n", n); printf("逆序对个数为:%lld \n", cnt); } return 0;}
运行结果
aha
好久没写过博客了,今天就写到这里了,欢迎小伙伴叨扰! merci…
- 分治法之归并排序
- 分治法之归并排序
- 分治法之归并排序
- 分治法之归并排序
- 分治法之归并排序
- 分治法之归并排序算法
- 分治法之二路归并排序
- [Algorithm_Learn_02]分治法之归并排序
- 分治法之归并排序1
- 【算法】分治法之归并排序实现
- 算法储备之归并排序(分治法)
- 分治法,归并排序
- 分治法-归并排序
- 分治法-归并排序
- 归并排序-分治法
- 分治法 - 归并排序
- 分治法--归并排序
- 归并排序 分治法
- 2017年10月13日笔记双边滤波的理解及结合另一篇博客的实现
- C语言 volatile 关键字
- Java三大器之拦截器(Interceptor)的实现原理及代码示例
- Java拦截器(interceptor)原理
- 微信小程序从子页面退回父页面时的数据传递 wx.navigateBack()
- 分治法之归并排序
- 【译】Sobel 算子文档
- Bootstrap
- 第一(2)部份 ic615 ubuntu mmsim bashrc设定
- DUT数模组第一周周记
- 自动化运维工具SaltStack详细部署及用SaltStack实现自动部署lamp架构
- 棋盘覆盖
- 一个ajax上传文件的简单案例
- java反转字符串