高效算法设计_再谈排序和检索(归并排序,逆序数对)
2017-08-11 09:17
447 查看
归并排序
上一个分治法的扩展
划分:把序列分成元素个数尽量相等的两半。递归求解:把两半的元素分别排序
合并:把两个有序表合并成一个
输入:
8 1 2 12 11 9 7 13 20
输出:
1 2 7 9 11 12 13 20
#include <stdio.h> #define MAXSIZE 1024 void merge_sort(int *A,int x,int y,int *T){ //T是辅助空间 int i; if(y-x>1){ //递归入口,所剩元素大于1,只有一个元素没有必要排序 int m=x+(y-x)/2;//分治第一步,划分,技巧,向中间靠拢 int p=x,q=m,i=x; merge_sort(A,x,m,T);//分治第二步,递归求解。 merge_sort(A,m,y,T); while(p<m||q<y){//只要有一个序列非空,就要继续合并 if(q>=y||(p<m&&A[p]<=A[q])) //第二个序列为空,或者两个序列都不为空,比较小的赋值,赋值A[p]. T[i++]=A[p++]; else T[i++]=A[q++]; //否则第二个不为空,且第一个为空,或者,两个都不为空,且A[p]<=A[q]时,才赋值A[q] } for(i=x;i<y;i++) A[i]=T[i]; //右边的y是取不到的 } } void print(int* A,int n)//比赛中避免最后一个空格检查出错误。 { for(int i = 0 ; i < n; i++) { if(i) { printf(" %d",A[i]); } else { printf("%d",A[i]); } } printf("\n"); } void process()//输入程序。 { int n; while(scanf("%d",&n)!=EOF) { int A[MAXSIZE]; int T[MAXSIZE]; for(int i = 0 ; i < n ; i++) { scanf("%d",&A[i]); } merge_sort(A,0,n,T); print(A,n); } } int main(int argc,char* argv[]) { process(); return 0; }
逆序对数
题目: 给一列数a1,a2,a3,…,an。求它的逆序对数,即有多少个有序对(i,j),使得i
输入:
8 1 9 6 3 4 7 9 0
输出:
0 1 2 3 3 4 6 6 10 12 13 13 0 1 3 4 6 7 9 9 13
第一行为计数过程表示cout逐渐自加的过程.
计算步骤:刚开始归并排序两两分组 (1,9)(6,3)||(4,7)(9,0)
后面一位和前面一位进行对比,如果 i<j 且 ai>aj,逆序数对就加1
对于前半部分 count=0+1; 重排合并后(1,9,3,6) count=0+1+1+1.
对于后半部分count=3+0+1;重排合并后(4,7,0,9)count=3+0+1+2+0;
然后再重排合并(1,3,6,9,0,4,7,9)count=6+4+2+1+0=13,及最终结果
#include <stdio.h> #define MAXSIZE 1024 int count,k=0; int K[MAXSIZE]; void mergeSort(int* A,int x,int y,int* T) { if(y-x>1) { int m = x + (y - x) / 2 ; int p=x,q=m,i=x; mergeSort(A,x,m,T); mergeSort(A,m,y,T); while(p < m || q < y) { //if(m >= high || (l < mid && iArr[l] < iArr[m])) if(q>= y||(p < m && A[p] <= A[q]))//=与号不能漏 { T[i++] = A[p++]; } else { T[i++]=A[q++]; count+=m-p; printf("%d ",count); } } for(int j = x ; j < y ; j++) { A[j]=T[j]; } } } void print(int* A,int n) { for(int i = 0 ; i < n; i++) { if(i) { printf(" %d",A[i]); } else { printf("%d",A[i]); } } printf("\n"); } void process() { int n; while(scanf("%d",&n)!=EOF) { count = 0; int A[MAXSIZE]; int T[MAXSIZE]; for(int i=0;i<n;i++) { scanf("%d",&A[i]); } mergeSort(A,0,n,T); print(A,n); printf("%d\n",count); } } int main() { process(); getchar(); return 0; }
相关文章推荐
- 算法竞赛入门经典:第八章 高效算法设计 8.2归并排序
- 排序-归并排序与求逆序数的算法--转帖-长见识了
- ( 设计高效算法 ) 年龄排序 Age Sort Uva 11462
- 算法竞赛入门经典:第八章 高效算法设计 8.3归并排序应用之逆序对数
- 【高效算法设计——扫描法】Amphiphilic Carbon Molecules 极角排序
- 紫书第八章-----高效算法设计(归并排序求逆序对数)
- 算法竞赛入门经典:第八章 高效算法设计 8.4快速排序应用之第k小的数
- 【算法学习笔记】20.算法设计初步 归并排序 求逆序数
- 紫书_第八章_高效算法设计_8.2.1——归并排序
- 紫书第八章-----高效算法设计(快速排序水题格式要求严)
- 归并排序和快速排序比较【算法设计与分析实验报告】
- 算法分析中最常用的几种排序算法(插入排序、希尔排序、冒泡排序、选择排序、快速排序,归并排序)C 语言版
- 二元树检索与周游算法设计与实现
- 【算法设计与分析】5个数7次比较排序的算法
- 【高效算法设计】1609 Building for UN
- 高效算法设计专项:LA 4726
- Java集合与数组实现升序排序的算法设计
- 空间换时间设计-多索引结构实现高效查询算法
- 排序算法之快速排序、归并排序(java实现)
- 算法竞赛入门经典:第八章 高效算法设计 8.12非线性方程求根