规并排序 以及 在其基础上的逆序对
2011-10-18 13:34
78 查看
写递归程序的时候,一定要注意其递归体的逻辑,另外假设子问题已经解决。
辅助函数只要解决好当前层自问体就好了,不要思考太多层次的东西,当然特殊的递归需求会有考虑多层次的东西。
merge(int l, int m, int r, int *a) {
l -> m
m+1->r 要合并
求逆序对个数的时候,可以在规并的过程中来数逆序对数。
L[]有序,R[]有序
那么L[I] <= R[J]时候,不需要累计逆序对数
否则L[I] > R[J]那么说明L[I] - > L[LEN_OF_LEFTPART] 都是与R[J]有逆序的关系。所以插入R[J]时候发现的逆序对数目是LEN_OF_LEFTPART-I+1
两边规并知道完成
return 当前层级的合并过程中的逆序对的个数。
}
merge_sort(int l, int r, int *a){
int cnt = 0, m = (l+r)>>1;
if( l < r ){
cnt += merge_sort(l, m, a); 左规并时候有几个逆序对
cnt += merge_sort(m+1,r, a);右规并的时候有几个逆序对
cnt += merge(l, m, r, a);当前曾规并的时候有几个逆序对,这个时候因为已经假设了右边和左边的是有序的。
}
return cnt;
}
源代码:
//============================================================================
// Name : integerPartition.cpp
// Author : jry
// Version :
// Copyright : Your copyright notice
// Description : Hello World in C++, Ansi-style
//============================================================================
#include <iostream>
#include<stdio.h>
#include<stdlib.h>
using namespace std;
int merger(int l, int m, int r, int* a){
int llen = m-l+1, rlen = r-m;
int *L = new int [(llen)];
int *R = new int [(rlen)];
int i = l, j = 0, k = 0, ttcnt = 0;
for(; i <= m; i++) L[j++] = a[i];
for(j = 0; i <= r; i++ ) R[j++] = a[i];
i = j = 0;
k = l;
while(i < llen && j < rlen){
if(L[i] <= R[j]) a[k++] = L[i++];
else {
a[k++] = R[j++];
ttcnt += llen - i;
}
}
while( i < llen ) a[k++] = L[i++];
while( j < rlen ) a[k++] = R[j++];
delete[] (L);
delete[] (R);
return ttcnt;
}
int merger_sort(int l, int r, int *a){
int m = (l+r) / 2;
int tcnt = 0;
if( l < r ) {
tcnt += merger_sort(l, m, a);
tcnt += merger_sort(m+1, r, a);
tcnt += merger(l, m, r, a);
}
return tcnt;
}
int main() {
int a[] = {4, 1, 2, 3, 5, 1};
bool TESTMSort = false;
int n = sizeof(a)/sizeof(int);
if(TESTMSort) { for( int i = 0; i < n; i ++ ) cout << a[i] << " "; cout << endl;}
cout << "逆序对数: " << merger_sort(0, n-1, a) << endl;
cout << "DONE" << endl; // prints DONE
return 0;
}
辅助函数只要解决好当前层自问体就好了,不要思考太多层次的东西,当然特殊的递归需求会有考虑多层次的东西。
merge(int l, int m, int r, int *a) {
l -> m
m+1->r 要合并
求逆序对个数的时候,可以在规并的过程中来数逆序对数。
L[]有序,R[]有序
那么L[I] <= R[J]时候,不需要累计逆序对数
否则L[I] > R[J]那么说明L[I] - > L[LEN_OF_LEFTPART] 都是与R[J]有逆序的关系。所以插入R[J]时候发现的逆序对数目是LEN_OF_LEFTPART-I+1
两边规并知道完成
return 当前层级的合并过程中的逆序对的个数。
}
merge_sort(int l, int r, int *a){
int cnt = 0, m = (l+r)>>1;
if( l < r ){
cnt += merge_sort(l, m, a); 左规并时候有几个逆序对
cnt += merge_sort(m+1,r, a);右规并的时候有几个逆序对
cnt += merge(l, m, r, a);当前曾规并的时候有几个逆序对,这个时候因为已经假设了右边和左边的是有序的。
}
return cnt;
}
源代码:
//============================================================================
// Name : integerPartition.cpp
// Author : jry
// Version :
// Copyright : Your copyright notice
// Description : Hello World in C++, Ansi-style
//============================================================================
#include <iostream>
#include<stdio.h>
#include<stdlib.h>
using namespace std;
int merger(int l, int m, int r, int* a){
int llen = m-l+1, rlen = r-m;
int *L = new int [(llen)];
int *R = new int [(rlen)];
int i = l, j = 0, k = 0, ttcnt = 0;
for(; i <= m; i++) L[j++] = a[i];
for(j = 0; i <= r; i++ ) R[j++] = a[i];
i = j = 0;
k = l;
while(i < llen && j < rlen){
if(L[i] <= R[j]) a[k++] = L[i++];
else {
a[k++] = R[j++];
ttcnt += llen - i;
}
}
while( i < llen ) a[k++] = L[i++];
while( j < rlen ) a[k++] = R[j++];
delete[] (L);
delete[] (R);
return ttcnt;
}
int merger_sort(int l, int r, int *a){
int m = (l+r) / 2;
int tcnt = 0;
if( l < r ) {
tcnt += merger_sort(l, m, a);
tcnt += merger_sort(m+1, r, a);
tcnt += merger(l, m, r, a);
}
return tcnt;
}
int main() {
int a[] = {4, 1, 2, 3, 5, 1};
bool TESTMSort = false;
int n = sizeof(a)/sizeof(int);
if(TESTMSort) { for( int i = 0; i < n; i ++ ) cout << a[i] << " "; cout << endl;}
cout << "逆序对数: " << merger_sort(0, n-1, a) << endl;
cout << "DONE" << endl; // prints DONE
return 0;
}
相关文章推荐
- 链表基础2(实现链表的逆序、将新结点插入到特定位置、边插结点边排序)
- javaAPI深入理解(2)Collection,List的设计,ListIterator与Iterator,RandomAccess,List排序、逆序以及其他
- 07--MySQL自学教程:DQL(Data Query Language:数据库查询语言)简介、基础查询、条件查询、模糊查询以及排序(一)
- JS基础篇--sort()方法的用法,参数以及排序原理
- 【Java】实现浮点数组的并集以及整型数组的交集和两个字符串数组的逆序排序
- 07--MySQL自学教程:DQL(Data Query Language:数据库查询语言)简介、基础查询、条件查询、模糊查询以及排序(一)
- JS基础篇--sort()方法的用法,参数以及排序原理
- 链表的实现以及合并,排序,逆序,等
- ACM:归并排序,以及利用归并排序思想求解逆序对数!
- JS基础篇--sort()方法的用法,参数以及排序原理
- Java基础知识强化之集合框架笔记69:Collections类之ArrayList存储自自定义对象并排序的案例
- 7.Spark Streaming:输入DStream之基础数据源以及基于HDFS的实时wordcount程序
- Kotlin基础语法之类型推断、类型转换、类型检查以及自动类型转换
- 蓝桥杯之基础练习 数列排序
- Java 从基础到进阶学习之路---类编写以及文档凝视.
- 基础算法之冒泡排序
- php四种基础排序(基础算法)----①冒泡排序法
- 关于动态存储分配函数的调用,在已经过排序的数组中查找及删除内容的操作,余数的分析,删除字符数组中的空格,对链表的逆置,在源字符串中查找子字符串的个数,函数指针以及函数的调用,循环赋值带来的问题以及插入
- 2017/08/24 排序的时间、空间复杂度以及稳定性
- 数组排序以及所需时间。。