您的位置:首页 > 编程语言 > C语言/C++

算法导论第三版 练手程序C++(第二章)(2)

2014-11-16 21:03 411 查看

实在闲的蛋疼,大神不要喷我

第二章

分治法排序:

伪代码:
MERGE(A,p,q,r)
n1 = q-p+1
n2 = r-q
新建数组 L[1..n1+1] 和 R[1..n2+1]
for i = 1 to n1
L[i] = A[p+i-1]
forj = 1 to n2
R[j] = A[q+j]
L[n1+1] = NaN
R[n2+1] = NaN
i = 1
j = 1
for k = p to r
if L[i]<=R[j]
A[k] = L[i]
i = j+1
else A[k] = R[j]
j = j+1

MERGE-SORT(A,p,r)
if p<r
q = |_(p+r)/2_|
MERGE-SORT(A,p,q)
MERGE-SORT(A,q+1,r)
MERGE(A,p,q,r)


这里有个蛋疼的问题,伪代码里,L和R每次调用merge时都是new出来(对C++而言)的,但是,要知道new一个数组画得时间远大于一般的计算,更不必说还要把new出来的数组delete掉了,那么咋办呢。。只好实现就新建一个全局的数组(类似缓存区的功能),每次需要新的数组时,直接利用全局数组,而merge里所需的数组的大小必然小于需要排序的数组的大小,那么,就创建一个和待排序数组大小一样的全局数组吧。
#include <stdlib.h>
#include <time.h>
#include <iostream>
#define PAI_LENGTH 10000
using namespace std;

int cache[PAI_LENGTH+2];

void merge(int A[],int p,int q,int r) {
int i,j;
int n1 = q-p+1;
int n2 = r-q;
int *L = cache;
int *R = cache+n1+1;
for(i = 0;i<n1;i++) {
L[i] = A[p+i];
}
for(j=0;j<n2;j++) {
R[j] = A[q+j+1];
}
L[n1] = 10000;
R[n2] = 10000;
i=0;
j=0;
for(int k=p;k<=r;k++) {
if(L[i]<=R[j]) {
A[k] = L[i];
i++;
}else{
A[k] = R[j];
j++;
}
}
}

void merge_sort(int A[],int p,int r) {
if(p<r) {
int  q = (p+r)/2;
merge_sort(A,p,q);
merge_sort(A,q+1,r);
merge(A,p,q,r);
}
}

void printAll(int A[],int length) {
for(int i=0;i<length;i++) {
cout<<A[i]<<endl;
}
}

int main() {
clock_t start,end;
int raw[PAI_LENGTH];
srand((unsigned)time(NULL));
for(int i=0;i<PAI_LENGTH;i++) {
raw[i] = rand()%10000+1;
}
start = clock();
merge_sort(raw,0,PAI_LENGTH-1);
end = clock();
cout<<"use"<<(end-start)<<"us"<<endl;
}
嗯,对,又是直接一大片代码。。其实看过上一篇的可以发现mian函数大部分的代码是在创建随机数组和计时的,看看结果:
use 4243 us
还有谁!!!同样10000个随机数,为什么分治算法这么快呢,没错,你没有看错,答案将会在第3,4章揭晓。。。。
下面顺便分享一下习题2.3-2的做法。要求是重写merge函数,使之不使用哨兵排,所以伪代码变成下面的样子:
MERGE(A,p,q,r)
n1 = q-p+1
n2 = r-q
let L[1..n1] and R[1..n2] be new arrays
for i = 1 to n1
L[i] = A[p+i-1]
forj = 1 to n2
R[j] = A[q+j]
i = 1
j = 1
k=p
while i<=n1 and j<=n2
if L[i]<=R[j]
A[k] = L[i]
i = j+1
else
A[k] = R[j]
j = j+1
k++
if i<=n1
for k=k to r
A[k]=R[j]
j=j+1
else
for k=k to r
A[k]=L[i]
i=i+1

MERGE-SORT(A,p,r)
if p<r
q = |_(p+r)/2_|
MERGE-SORT(A,p,q)
MERGE-SORT(A,q+1,r)
MERGE(A,p,q,r)


恩好像没差嘛。看看对应的程序:
#include <stdlib.h>
#include <time.h>
#include <iostream>
#define PAI_LENGTH 10000
using namespace std;

int cache[PAI_LENGTH+2];

void merge(int A[],int p,int q,int r) {
int i,j;
int n1 = q-p+1;
int n2 = r-q;
int *L = cache;
int *R = cache+n1;
for(i = 0;i<n1;i++) {
L[i] = A[p+i];
}
for(j = 0;j<n2;j++) {
R[j] = A[q+j+1];
}
i=0;
j=0;
int k=p;
for(;i<n1&&j<n2;k++) {
if(L[i]<=R[j]) {
A[k] = L[i];
i++;
}else{
A[k] = R[j];
j++;
}
}
if(i>=n1) {
for(;k<=r;k++) {
A[k] = R[j];
j++;
}
}else{
for(;k<=r;k++) {
A[k] = L[i];
i++;
}
}
}

void merge_sort(int A[],int p,int r) {
if(p<r) {
int  q = (p+r)/2;
merge_sort(A,p,q);
merge_sort(A,q+1,r);
merge(A,p,q,r);
}
}

void printAll(int A[],int length) {
for(int i=0;i<length;i++) {
cout<<A[i]<<endl;
}
}

int main() {
clock_t start,end;
int raw[PAI_LENGTH];
srand((unsigned)time(NULL));
for(int i=0;i<PAI_LENGTH;i++) {
raw[i] = rand()%10000+1;
}
start = clock();
merge_sort(raw,0,PAI_LENGTH-1);
end = clock();
printAll(raw,PAI_LENGTH);
cout<<"use"<<(end-start)<<"us"<<endl;
}


恩,好像也没差嘛。。。
再看看运行结果:
use 4297 us 
恩,果然没差。。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息