1、算法理论与分析实验实验一:1、问题描述: 设计一个满足以下要求的比赛日程表: (1) 每个选手必须与其他n-1个选手各赛一次; (2) 每个选手一天只能赛一次; (3) 循环赛一共进行n-1天。 用分治法实现。2、算法描述: 按分治策略,将所有分为两半,n个选手可以通过n/2个选手设计的比赛日程表来决定。递归地用一分为二的略对选手进行分割,直到只剩下两个选手。对于n为奇数的情况可以虚拟多一个选手,使其编程n+1个选手的日程表,最然后忽略虚拟运动员参与的比赛。对于分割时候n/2的情况也做特殊处理, 前n/2轮比赛空选手与下一个未参赛的选手进行比赛。伪代码如下:void tournament(in
2、t m) if(m=1) A00=1; return ; else if(isodd(m) /如果m为奇数,则m+1是偶数 tournament(m+1); /按照偶数个选手来求解 replaceVirtual(m+1); /然后把第m+1号虚选手置成0 return ; else /r如果m是偶数, tournament(m/2); /分治,先安排第1组的m/2人比赛 makecopy(m); /合并,根据算法,构造左下、右下、右上、右下的矩阵 return ;/判断m的奇偶性bool isodd(m) Return m&1; /m为奇数,返回1,m为偶数,返回0/*makecopy:当前有
3、m位(偶数)选手,分成两组,每组由m/2位选手构成 由第一组的m/2位选手的安排来构成第二组的比赛安排,第一 组与第二组的比赛安排。要区分m/2为奇数和偶数两种情况*/void makecopy(int m) if (isodd(m/2) /m/2为奇数 copyodd(m/2); else /m/2为偶数 copyeven(m/2);/*copyeven:m为偶数时用,由前1组的m位选手的安排,来构成第2组m位选手 的赛程安排,以及两组之间的比赛安排 */void copyeven(int m) if(isodd(m) return; int i,j; for (j=0;jm;j+) /1.
4、 求第2组的安排(+m) for (i=0;im;i+) Ai+mj=Aij+m; for (j=m;j2*m;j+)/两组间比赛的安排 for (i=0;im;i+) /2. 第1组和第2组 Aij=Ai+mj-m; /把左下角拷贝到右上角 for (i=m;i2*m;i+) /3. 对应的,第2组和第1组 Aij=Ai-mj-m; /把左上角拷贝到右下角 return;/*copyodd:m为奇数时用,由前1组的m位选手的安排,来构成第2组m位选手 的赛程安排,以及两组之间的比赛安排。这时和m为偶数时的 处理有区别。*/void copyodd(int m) int i,j; for (j
5、=0;j=m;j+) /1. 求第2组的安排(前m天) for (i=0;im;i+)/行 if (Aij!=0) Ai+mj=Aij+m; else /特殊处理:两个队各有一名选手有空,安排他们比赛 Ai+mj = i+1; Aij = i+m+1; /安排两组选手之间的比赛(后m-1天) for(i=0,j=m+1;j2*m;j+) Aij = j+1; /2. 1号选手的后m-1天比赛 A (Aij -1) j = i+1; /3. 他的对手后m-1天的安排 /以下的取值要依赖于1号选手的安排,所以之前先安排1号的赛程 for (i=1;im;i+) /第1组的其他选手的后m-1天的安排
6、 for (j=m+1;j2*m;j+) /2. 观察得到的规则一:向下m+12*m循环递增 Aij = (Ai-1j+1)%m=0)?Ai-1j+1 :m + (Ai-1j+1)%m; /3. 对应第2组的对手也要做相应的安排 A (Aij-1) j = i+1; return;3、运行结果 当N为奇数时,结果截图: 当N为偶数时,结果截图: 4、源程序#include#includeint *A; /int *指针数组,int *schedule; /int数组,一维数组保存二维数组的数据int N =1; /问题的规模。初始化时会设定/isodd:判断x是否奇数,是则返回1,否则0int
7、 isodd(int x) return x&1;/print:打印赛程void print() int i,j, row, col; if(isodd(N) row=N; col=N+1; else row=N; col=N; printf(第1列是选手编号n); for(i=0;irow; i+) for(j=0;jcol; j+) printf(%4d, Aij); printf(n); /*init:初始化,设置问题规模N值,分配内存,用schedule指向; 把A构造成一个二维数组*/void init() int i, n; char line100=0; printf(请输入选手
8、人数:); fgets(line,sizeof(line), stdin); N=atoi(line); if(N=0) exit(-1); if(isodd(N) n=N+1; else n=N; /schedule是行化的二维数组 schedule=(int *)calloc(n*n, sizeof(int); A=(int *)calloc(n, sizeof(int *); if(!schedule | A=NULL) exit(-2); for(i=0;in;i+) /把A等价为二维数组 Ai=schedule+i*n; Ai0=i+1;/初始化这个数组的第一列 return;/*r
9、eplaceVirtual:把第m号虚的选手去掉(换做0)*/void replaceVirtual(int m) int i,j; for(i=0;im-1;i+) /行:对应选手号1m-1 for (j=0;j=m;j+) /列: 比行要多1 Aij = (Aij=m)?0:Aij; return;/*copyeven:m为偶数时用,由前1组的m位选手的安排,来构成第2组m位选手 的赛程安排,以及两组之间的比赛安排 */void copyeven(int m) if(isodd(m) return; int i,j; for (j=0;jm;j+) /1. 求第2组的安排(+m) for
10、(i=0;im;i+) Ai+mj=Aij+m; for (j=m;j2*m;j+)/两组间比赛的安排 for (i=0;im;i+) /2. 第1组和第2组 Aij=Ai+mj-m; /把左下角拷贝到右上角 for (i=m;i2*m;i+) /3. 对应的,第2组和第1组 Aij=Ai-mj-m; /把左上角拷贝到右下角 return;/*copyodd:m为奇数时用,由前1组的m位选手的安排,来构成第2组m位选手 的赛程安排,以及两组之间的比赛安排。这时和m为偶数时的 处理有区别。*/void copyodd(int m) int i,j; for (j=0;j=m;j+) /1. 求第
11、2组的安排(前m天) for (i=0;im;i+)/行 if (Aij!=0) Ai+mj=Aij+m; else /特殊处理:两个队各有一名选手有空,安排他们比赛 Ai+mj = i+1; Aij = i+m+1; /安排两组选手之间的比赛(后m-1天) for(i=0,j=m+1;j2*m;j+) Aij = j+1; /2. 1号选手的后m-1天比赛 A (Aij -1) j = i+1; /3. 他的对手后m-1天的安排 /以下的取值要依赖于1号选手的安排,所以之前先安排1号的赛程 for (i=1;im;i+) /第1组的其他选手的后m-1天的安排 for (j=m+1;j2*m;
12、j+) /2. 观察得到的规则一:向下m+12*m循环递增 Aij = (Ai-1j+1)%m=0)?Ai-1j+1 :m + (Ai-1j+1)%m; /3. 对应第2组的对手也要做相应的安排 A (Aij-1) j = i+1; return;/*makecopy:当前有m位(偶数)选手,分成两组,每组由m/2位选手构成 由第一组的m/2位选手的安排来构成第二组的比赛安排,第一 组与第二组的比赛安排。要区分m/2为奇数和偶数两种情况*/void makecopy(int m) if (isodd(m/2) /m/2为奇数 copyodd(m/2); else /m/2为偶数 copyeve
13、n(m/2);void tournament(int m) if(m=1) A00=1; return ; else if(isodd(m) /如果m为奇数,则m+1是偶数 tournament(m+1); /按照偶数个选手来求解 replaceVirtual(m+1); /然后把第m+1号虚选手置成0 return ; else /m是偶数, tournament(m/2); /则先安排第1组的m/2人比赛 makecopy(m); /然后根据算法,构造左下、右下、右上、右下的矩阵 return ;/*endprogram:回收分配的内存*/void endprogram() free(sc
14、hedule); free(A); int main() init(); /初始化 tournament(N);/求解 print(); /打印结果 endprogram(); /回收内存 return 0;实验二:1、问题描述: 采用舍伍德(Sherwood )思想,完成快速排序。写一算法实现。2、算法描述: 在这里,用舍伍德型选择算法随机的选择一个数组元素作为划分标准。这样既能保证算法的线性时间平均性能又避免了计算拟中位数的麻烦。非递归的舍伍德型算法可描述如下:templateType select(Type a, int l,int r, int k)/计算al:r中第K个元素 stat
15、ic RandomNumber rnd; while(true) if(l=r) return al; int i = l; j = l + rnd.Random(r-l+1);/随机选择的划分基准 Swap(ai,aj); j = r + 1; Type pivot = al; /以划分基准为轴作元素交换 while(true) while(a+ipivot); if(i=j) break; Swap(ai,aj); if(j-l+1=k) return pivot; al=aj; aj=pivot; /对子数组重复划分过程 if(j-l+1k) k=k-j+l-1; l=j+1; else
16、 r=j-1; templateType Select(Type a,int n,int k) /计算a0:n-1中第K小元素 /假设an是一个键值无穷大的元素 if(kn) throw OutOfBounds(); return select(a,0,n-1,k);3、实验结果Number:100000Number:10000Number:1000Number:100Number:10Number:1 4、源程序random.h#include #include using namespace std;/ generate random numbersclass randomNumber p
17、ublic: randomNumber(long s = 0); / initialize the random number generator long random(); / return a 32-bit random integer m, 1 = m = 231-2 / return a 32-bit random integer m, 0 = m = n-1, / where n = 231-1 long random(long n); / return a real number x, 0 = x 1 double frandom(); private: static const
18、 long A; static const long M; static const long Q; static const long R; long seed;const long randomNumber:A = 48271;const long randomNumber:M = 2147483647;const long randomNumber:Q = M / A;const long randomNumber:R = M % A;randomNumber:randomNumber(long s) if (s 0, 0) s = t_time 0x5EECE66DL; else if
19、 (t_time = 0 ) seed = tmpSeed; else seed = tmpSeed + M; return seed;long randomNumber:random(long n) double fraction = double(random()/double(M); return int(fraction * n);double randomNumber:frandom() return double(random()/double(M);timer.h#ifndef TIMER_CLASS#define TIMER_CLASS#include / declares c
20、lock_t type, function clock(), / and constant CLOCKS_PER_SECclass timer private: / starting and ending time measured in clock ticks clock_t startTime, endTime; public: timer(); / initialize the timer. / Postconditions: set the starting and ending event times to 0. / this creates an event whose time
21、is 0.0 void start(); / start timing an event. / Postcondition: record the current time as the starting time void stop(); / stop timing an event. / Postconditon: record the current time as the ending time double time() const; / return the time the event took in seconds by computing / the difference b
22、etween the ending and starting times.;/ */ timer class implementation/ */ constructor. set starting and ending times to 0timer:timer():startTime(0), endTime(0)/ determine clock ticks at startvoid timer:start() startTime = clock();/ determine clock ticks at endvoid timer:stop() endTime = clock();/ re
23、turn the elapsed time in secondsdouble timer:time() const return (endTime-startTime)/double(CLOCKS_PER_SEC);#endif / TIMER_CLASSsherwood.cpp#include #include random.h#include timer.h#define NUMBER 100000 /自定义排序数组的大小templatevoid QuickSort(Type a, int p, int r) if(p r) int q = Partition(a,p,r); QuickS
24、ort(a,p,q-1); QuickSort(a,q+1,r); templateint RandomizedPartition(Type a, int p, int r) randomNumber rand; /产生一个大于等于p小于等于r的值 int i = p + rand.random(r-p+1); Type temp; /交换ai与aj的值 temp = ai; ai = ap; ap = temp; return Partition(a, p, r);templateint Partition(Type a, int p, int r) int i = p, j = r + 1; Type temp; Type x = ap; /将 小于 x 的元素交换到左边区域,大于 x 的元素交换到右边区域 while(true) while(a+i x & i x); if(i = j) break; temp = ai; ai = aj; aj = temp; ap = aj; aj = x; return j; templatevoid RandomizedQuickSort(Type a, int p, int r) if(pr) int q
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1