算法设计实验1

合集下载

算法与程序设计实验一实验报告.docx

算法与程序设计实验一实验报告.docx

实验一:C程序的运行环境和运行C程序的方法
(5)输入并编辑一个有错误的C程序。

a.输入教材第1章例1.2,故意漏打或打错几个字符。

b.进行编译,仔细分析编译信息窗口,可能显示有多个错误,进行修改,直到不出现错误。

最后请
与教材上的程序对照。

c.使程序运行,分析运行结果。

(6)输入并运行一个需要在运行时输入数据的程序。

a.输入下面的程序:
# include<stdio.h>
int max (int x, int y)
{ int z;
if (x>y) z=x;
else z=y;
)运行一个自己编写的程序。

题目是教材第1章的习题1.6。

即输入a、b、c 3个值,输出其中最大者。

1)输入自己编写的源程序;
检查程序有无错误(包括语法错误和逻辑错误),有则改之。

编译和连接,仔细分析编译信息,如有错误,应找出原因并改正之。

运行程序,输入数据,分析结果。

运算结果。

算法设计与分析实验报告

算法设计与分析实验报告

实验报告题目实验一递归与分治策略一、实验目的1.加深学生对分治法算法设计方法的基本思想、基本步骤、基本方法的理解与掌握;2.提高学生利用课堂所学知识解决实际问题的能力;3.提高学生综合应用所学知识解决实际问题的能力。

二、实验内容设计一个递归和分治算法,找出数组的最大元素,找出x在数组A中出现的次数。

三、实验要求(1)用分治法求解…问题;(2)再选择自己熟悉的其它方法求解本问题;(3)上机实现所设计的所有算法;四、实验过程设计(算法设计过程)1.设计一个递归算法,找出数组的最大元素。

2.设计一个分治算法,找出x在数组A中出现的次数。

3.写一个主函数,调用上述算法。

五、实验结果分析(分析时空复杂性,设计测试用例及测试结果)时间复杂性:最好情况下,O(n)最坏情况下:O(nlog(n)空间复杂性分析:O(n)六、实验体会通过写递归与分治策略实验,更加清楚的知道它的运行机理,分治法解题的一般步骤:(1)分解,将要解决的问题划分成若干规模较小的同类问题;(2)求解,当子问题划分得足够小时,用较简单的方法解决;(3)合并,按原问题的要求,将子问题的解逐层合并构成原问题的解。

做实验重在动手动脑,还是要多写写实验,才是硬道理。

七、附录:(源代码)#include"stdio.h"#define ElemType intint count(ElemType a[],int i,int j,ElemType x){int k=0,mid; //k用来计数,记录数组中x出现的次数if(i==j){if(a[i]==x) k++;return k;}else{mid=(i+j)/2;k+=count(a,i,mid,x);k+=count(a,mid+1,j,x);}return k;}ElemType Maxitem(ElemType a[],int n){ElemType max=a[n-1],j;if(n==1){max=a[n-1];return max;}else{j=Maxitem(a,n-1);if(j>max) max=j;return max;}}void main(void){ElemType a[]={1,5,2,7,3,7,4,8,9,5,4,544,2,4,123};ElemType b;ElemType x;int n;b=Maxitem(a,15);printf("数组的最大元素为%d\n",b);printf("输入想要计数的数组元素:\n");scanf("%d",&x);n=count(a,0,14,x);printf("%d在数组中出现的次数为%d次\n",x,n);}实验二动态规划——求解最优问题一、实验目的1.加深学生对动态规划算法设计方法的基本思想、基本步骤、基本方法的理解与掌握;2.提高学生利用课堂所学知识解决实际问题的能力;3.提高学生综合应用所学知识解决实际问题的能力。

算法设计_实验报告

算法设计_实验报告

通过本次实验,加深对算法设计方法的理解,掌握常用算法的原理和实现方法,提高编程能力。

二、实验内容1. 矩阵链乘问题2. 投资问题3. 完全背包问题4. 数字三角形问题5. 最小生成树问题三、实验原理1. 矩阵链乘问题矩阵链乘问题是指给定一系列矩阵,求这些矩阵连乘的乘积的最小计算代价。

动态规划方法可以有效地解决这个问题。

2. 投资问题投资问题是指给定一组投资方案和初始资金,求在有限的时间内,如何选择投资方案使得最终收益最大。

动态规划方法可以解决这个问题。

3. 完全背包问题完全背包问题是指给定一组物品和背包的容量,求在不超过背包容量的前提下,如何选择物品使得背包中物品的总价值最大。

动态规划方法可以解决这个问题。

4. 数字三角形问题数字三角形问题是指给定一个数字三角形,从顶部到底部求出一条路径,使得路径上的数字之和最大。

动态规划方法可以解决这个问题。

5. 最小生成树问题最小生成树问题是指给定一个加权无向图,求一个包含图中所有顶点的最小生成树。

Prim算法和Kruskal算法是解决此问题的常用算法。

1. 矩阵链乘问题(1)定义一个二维数组dp,dp[i][j]表示从矩阵A[i]到矩阵A[j]的最小计算代价。

(2)初始化dp[i][i]为0,表示单个矩阵的计算代价为0。

(3)对于长度为2的矩阵链,dp[i][i+1]等于矩阵A[i]和A[i+1]的乘积。

(4)对于长度大于2的矩阵链,通过遍历所有可能的分割点,计算dp[i][j]的最小值。

2. 投资问题(1)定义一个二维数组dp,dp[i][j]表示在前i个投资方案中,使用j元资金所能获得的最大收益。

(2)初始化dp[0][0]为0,表示不投资时收益为0。

(3)对于第i个投资方案,遍历所有可能的资金使用情况,更新dp[i][j]的值。

3. 完全背包问题(1)定义一个二维数组dp,dp[i][j]表示在前i个物品中,使用容量为j的背包所能获得的最大价值。

(2)初始化dp[0][0]为0,表示不放入任何物品时价值为0。

算法设计与分析实验报告—01背包问题

算法设计与分析实验报告—01背包问题

算法设计与分析实验报告—0/1背包问题-【问题描述】给定n 种物品和一个背包。

物品i 的重量是iw ,其价值为i v,背包容量为C 。

问应该如何选择装入背包的物品,使得装入背包中物品的总价值最大?【问题分析】0/1背包问题的可形式化描述为:给定C>0, i w >0, i v >0,1i n ≤≤,要求找出n 元0/1向量{}12(,,...,),0,1,1n i x x x x i n ∈≤≤,使得n1i i i w x c =≤∑,而且n1i ii v x=∑达到最大。

因此0/1背包问题是一个特殊的整数规划问题。

0n k w ≤≤1max ni i i v x =∑n1i ii w xc =≤∑{}0,1,1i x i n ∈≤≤【算法设计】设0/1背包问题的最优值为m( i, j ),即背包容量是j ,可选择物品为i,i+1,…,n 时0/1背包问题的最优值。

由0/1背包问题的最优子结构性质,可以建立计算m( i, j )的递归式如下:max{m( i+1, j ), m( i+1, j-i w )+i v } i j w ≥m( i, j )=m(i+1,j)n v n j w >m(n,j)=0 0n k w ≤≤【算法实现】#include <iostream.h> #include<string.h> #include<iomanip.h>int min(int w, int c) {int temp; if (w < c) temp = w;elsetemp = c;return temp;}Int max(int w, int c) {int temp; if (w > c) temp = w;elsetemp = c;return temp;}void knapsack(int v[], int w[], int** m, int c, int n) //求最优值 {int jmax = min(w[n]-1, c);for (int j = 0; j <= jmax; j++)m[n][j] = 0;for (int jj = w[n]; jj <= c; jj++)m[n][jj] = v[n];for(int i = n-1; i > 1; i--)//递归部分{jmax = min(w[i]-1, c);for(int j = 0; j <= jmax; j++)m[i][j] = m[i+1][j];for(int jj = w[i]; jj <= c; jj++)m[i][jj] = max(m[i+1][jj], m[i+1][jj-w[i]]+v[i]);}m[1][c] = m[2][c];if(c >= w[1])m[1][c] = max(m[1][c], m[2][c-w[1]]+v[1]);cout << endl << "最优值:" << m[1][c] << endl;cout<<endl;cout<< "&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&" << endl;}int traceback(int x[], int w[], int** m, int c, int n) //回代,求最优解{out << endl << "得到的一组最优解如下: " << endl;for(int i = 1; i < n; i++){if(m[i][c] == m[i+1][c]) x[i] = 0;else{x[i] = 1;c -= w[i];}}x[n] = (m[n][c]) ? 1:0;for(int y = 1; y <= n; y++)cout << x[y] << "\t";cout << endl;return x[n];}void main(){int n, c;int **m;cout << "&&&&&&&&&&&&&&&&&&&&&欢迎使用0-1背包问题程序&&&&&&&&&&&&&&&&&&&" << endl;cout << "请输入物品个数: ";cin >> n ;cout << endl << "请输入背包的承重:";cin >> c;int *v = new int[n+1];cout << endl << "请输入每个物品的价值 (v[i]): " << endl;for(int i = 1; i <= n; i++)cin >> v[i];int *w = new int[n+1];cout << endl << "请输入每个物品的重量 (w[i]): " << endl;for(int j = 1; j <= n; j++)cin >> w[j];int *x = new int[n+1];m = new int* [n+1]; //动态的分配二维数组for(int p = 0; p < n+1; p++)m[p] = new int[c+1];knapsack (v, w, m, c, n);traceback(x, w, m, c, n);}【运行结果】。

算法课设实验报告(3篇)

算法课设实验报告(3篇)

第1篇一、实验背景与目的随着计算机技术的飞速发展,算法在计算机科学中扮演着至关重要的角色。

为了加深对算法设计与分析的理解,提高实际应用能力,本实验课程设计旨在通过实际操作,让学生掌握算法设计与分析的基本方法,学会运用所学知识解决实际问题。

二、实验内容与步骤本次实验共分为三个部分,分别为排序算法、贪心算法和动态规划算法的设计与实现。

1. 排序算法(1)实验目的:熟悉常见的排序算法,理解其原理,比较其优缺点,并实现至少三种排序算法。

(2)实验内容:- 实现冒泡排序、快速排序和归并排序三种算法。

- 对每种算法进行时间复杂度和空间复杂度的分析。

- 编写测试程序,对算法进行性能测试,比较不同算法的优劣。

(3)实验步骤:- 分析冒泡排序、快速排序和归并排序的原理。

- 编写三种排序算法的代码。

- 分析代码的时间复杂度和空间复杂度。

- 编写测试程序,生成随机测试数据,测试三种算法的性能。

- 比较三种算法的运行时间和内存占用。

2. 贪心算法(1)实验目的:理解贪心算法的基本思想,掌握贪心算法的解题步骤,并实现一个贪心算法问题。

(2)实验内容:- 实现一个贪心算法问题,如活动选择问题。

- 分析贪心算法的正确性,并证明其最优性。

(3)实验步骤:- 分析活动选择问题的贪心策略。

- 编写贪心算法的代码。

- 分析贪心算法的正确性,并证明其最优性。

- 编写测试程序,验证贪心算法的正确性。

3. 动态规划算法(1)实验目的:理解动态规划算法的基本思想,掌握动态规划算法的解题步骤,并实现一个动态规划算法问题。

(2)实验内容:- 实现一个动态规划算法问题,如背包问题。

- 分析动态规划算法的正确性,并证明其最优性。

(3)实验步骤:- 分析背包问题的动态规划策略。

- 编写动态规划算法的代码。

- 分析动态规划算法的正确性,并证明其最优性。

- 编写测试程序,验证动态规划算法的正确性。

三、实验结果与分析1. 排序算法实验结果:- 冒泡排序:时间复杂度O(n^2),空间复杂度O(1)。

实验1-古典密码算法

实验1-古典密码算法

实验1-古典密码算法一、实验目的通过编程实现替代密码算法和置换密码算法,加深对古典密码体系的了解,为以后深入学习密码学奠定基础。

二、实验原理古典密码算法曾被广泛应用,大都比较简单。

它的主要应用对象是文字信息,利用密码算法实现文字信息的加密和解密。

其中替代密码和置换密码是具有代表性的两种古典密码算法。

1、替代密码替代密码算法的原理是使用替代法进行加密,就是将明文中的字符用其他字符替代后形成密文。

例如,明文字母a、b、c、d,用D、E、F、G做对应替换后形成密文。

最早的替代密码是由Julius Caesar 发明的Caesar (恺撒)密码,又叫循环移位密码。

它的加密过程可以表示为下面的函数:E(m) = (m+k ) mod n其中,m为明文字母在字母表中的位置数;n为字母表中的字母个数;k为密钥;E(m)为密文字母在字母表中对应的位置数。

例如,对于明文字母H,其在字母表中的位置数为8,设k=4,则按照上式计算出来的密文为L,计算过程如下:E(8) = (m+k ) mod n = (8+4 ) mod 26 = 12 = L 解密算法是:m = D(L) =(L-k)mod 262、置换密码置换密码算法的原理是不改变明文字符,只将字符在明文中的排列顺序改变,从而实现明文信息的加密。

置换密码又称为换位密码。

矩阵换位法是实现置换密码的一种常用方法。

它将明文中的字母按照给定的顺序安排在一个矩阵中,然后又根据密钥提供的顺序重新组合矩阵中的字母,从而形成密文。

例如,明文为 attack begins at five ,密钥为 cipher ,将明文按照每行6个字母的形式排在矩阵中,形成如下形式:a t t a c kb e g i n sa t f i v e根据密钥 cipher 中各字母在字母表中出现的先后顺序,得到给定的一个置换:f = 1 4 5 3 2 6因此有:密钥: 1 4 5 3 2 6明文: a t t a c kb e g i n sa t f i v e根据上面的置换,将原有矩阵中的字母按照第1列、第4列、第5列、第3列、第2列、第6列的顺序排列、则有下面的形式:a a c t t kb i n g e sa i v f t e从而得到密文:abatgftetcnvaiikse其解密过程是根据密钥的字母数作为列数,将密文按照列、行的顺序写出,再根据由密钥给出的矩阵置换产生新的矩阵,从而恢复明文。

算法分析与设计实验一

算法分析与设计实验一实验内容分别针对随机生成的三组整数序列(规模为1000个数、10000个数、100000个数)进行排序,排序算法使用以下五种经典的方法,分别是:冒泡排序算法,选择排序算法,插入排序算法,归并排序算法和快速排序算法。

实验目的回顾并熟悉常用的排序算法。

通过实验体会算法设计对问题求解效率所产生的深刻影响。

算法设计的基本思路选择排序在要排序的一组数中,选出最小的一个数与第一个位置的数交换;然后在剩下的数当中再找最小的与第二个位置的数交换,如此循环到倒数第二个数和最后一个数比较为止。

直接插入排序在要排序的一组数中,假设前面(n-1)[n=2]个数已经是排好顺序的,现在要把第n个数插到前面的有序数中,使得这n个数也是排好顺序的。

如此反复循环,直到全部排好顺序。

冒泡排序在要排序的一组数中,对当前还未排好序的范围内的全部数,自上而下对相邻的两个数依次进行比较和调整,让较大的数往下沉,较小的往上冒。

即:每当两相邻的数比较后发现它们的排序与排序要求相反时,就将它们互换。

归并排序算法合并排序(MERGE SORT)是又一类不同的排序方法,合并的含义就是将两个或两个以上的有序数据序列合并成一个新的有序数据序列,因此它又叫归并算法。

它的基本思想就是假设数组A有N个元素,那么可以看成数组A是又N个有序的子序列组成,每个子序列的长度为1,然后再两两合并,得到了一个N/2个长度为2或1的有序子序列,再两两合并,如此重复,直到得到一个长度为N的有序数据序列为止,这种排序方法称为2-路合并排序。

快速排序快速排序是对冒泡排序的一种本质改进。

它的基本思想是通过一趟扫描后,使得排序序列的长度能大幅度地减少。

在冒泡排序中,一次扫描只能确保最大数值的数移到正确位置,而待排序序列的长度可能只减少1。

快速排序通过一趟扫描,就能确保某个数(以它为基准点吧)的左边各数都比它小,右边各数都比它大。

然后又用同样的方法处理它左右两边的数,直到基准点的左右只有一个元素为止。

算法实验报告一

问题:试验3hanoi调试错误
解决方法:算法需要定义move函数,才能实现函数的调用;
问题:出现未定义字母
解决方法:检查代码是否有错误,是否正确定义并改正。
System.out.println("结果为:"+q(5,6));
publicstaticvoidmain(String[] args) {
}
publicstaticintq(intn,intm) {
if((n<1)||(m<1))return0;
if((n==1)||(m==1))return1;
时加入c将n1个较小的圆盘依次移动规则从a到c然后将剩下的最大圆盘移至b最后在设法将n1个较小的圆盘依次移动规则从c到b
《算法设计与分析》课程实验报告
专业:计算机科学与技术
班级:
学号:
姓名:
日期:2014年10月18日
一、实验题目
熟悉环境和递归算法
二、实验目的
1、熟悉Java上机环境;
2、基本掌握递归算法的原理方法.
(ri)perm(X)表示在全排列perm(X)的每一个排列前加上前缀得到的排列。R的全排列可归纳定义如下:
当n=1时,perm(R)=(r),其中r是集合R中唯一的元素;
当n>1时,perm(R)由(r1)perm(R1),(r2)perm(R2),…,(rn)perm(Rn)构成。
(2)算法描述
if(n > 0) {
hanoi(n-1, a, c, b);
Move(a, b);
hanoi(n-1, c, b, a);
}
}
privatestaticvoidMove(chara,charb) {

算法实验

《算法设计与分析》实验一 用贪心方法解背包问题一: 实验目的掌握按贪心方法原理求背包问题最优解的方法二:问题描述背包问题描述如下: 已知背包容量M=120物品种类数n=10各种物品的总效益pi(i=1,2,………10) : 50,60,70,80,90,80,70,60,50,40 各种物品的总重量wi(i=1,2………10) : 17,30,25,41,80,70,64,56,47,38 求: 各种物品所取重量占其总重量的比例xi(i=1,2,…..10),满足0<=xi<=1, 且 且使得 达到最大值.三. 基本要求(1) 按三种不同的量度标准分别计算所得最大总效益,然后比较哪个最大1.按效益值由大到小取物品.2. 按重量值由小到大取物品3.按比值pi/wi 的值由大到小取物品 物品序号i 1 2 3 4 5 6 7 8 9 10 总效益(1) x1 0 0 0 0.976 1 0 0 0 0 0 168.05(2) x2 1 1 1 0.244 0 0 0 0 0 1 239.51(3) x3 1 1 1 1 0 0.1 0 0 0 0 268.00 结论:按(3) 的量度标准计算所得所取全部物品总效益之和最大四.重点和难点∑=<=n i MWixi1∑=n i pixi1(1)用贪心方法原理理解实际问题(2)函数之间的调用(3)排序算法实验二求图的任两结点间的距离一: 实验目的掌握按动态规划原理解决计算图的任两结点间的距离的Floyd算法二:问题描述设图G 的结点个数n=10,给定一个10*10矩阵作为图G 的成本矩阵.其中的元素99相当于无穷,表示相应的两个结点间没有边相连0 99 8 7 6 5 4 3 2 199 0 99 8 7 6 5 4 3 28 99 0 99 8 7 6 5 4 37 8 99 0 99 8 7 6 5 4C= 6 7 8 99 0 99 8 7 6 55 6 7 8 99 0 99 8 7 64 5 6 7 8 99 0 99 8 73 4 5 6 7 8 99 0 99 82 3 4 5 6 7 8 99 0 991 2 3 4 5 6 7 8 99 0三. 基本要求(1)用二维数组存放C ,C是原成本矩阵(2)算法采用三重循环(3)本题运行结果0 3 4 5 6 5 4 3 2 13 0 5 6 7 6 54 3 24 5 0 7 8 7 6 5 4 35 6 7 0 9 8 7 6 5 46 7 8 9 0 11 8 7 6 55 6 7 8 11 0 9 8 7 64 5 6 7 8 9 0 7 6 53 4 5 6 7 8 7 0 5 42 3 4 5 6 7 6 5 0 31 2 3 4 5 6 5 4 3 0四.重点和难点(1)掌握按动态规划原理(2)计算图的任两结点间的距离的Floyd算法实验三流水线调度问题一: 实验目的掌握按动态规划原理求解一类特定条件下的流水线调度问题具体做法.二:问题描述已知作业个数n=10各个作业第一道工序所须时间ai(I=1,2……,n)各个作业第二道工序所须时间bi(I=1,2……,n)作业序号: 1 2 3 4 5 6 7 8 9 10 a; 25 30 35 40 45 50 55 60 65 70 b; 21 31 41 51 61 39 49 59 69 79规定: (1)任一个作业必须先做完第一道工序才能做第二道工序(2) 任一个作业的任一道工序必须连续做完,才能中断而让别的作业做完.求: 一种最优调度方案,即使总的完成时间最短的调度方案,用长度为n的一维数组s表示,使s[i]为按先后次序排在第i位进行处理的作业的序号.三:要求:(1)用一个4*20的二维数组M,第1行存放按从小到大排序的20个所给出的ai和bi,第2行存放相应的作业序号,第3行存放1或2(1代表是来自ai,2代表是来自bi), 第4行存放0或1(0代表作业序号未进入最优调度方案;1代表作业序号已进入最优调度方案)(2)排序完后,按课本所述方法求一种最优调度方案,存放在S中。

计算机算法与分析实验1

实验一:递归与分治策略一、实验目的:理解并熟悉使用递归与分治来解决问题。

二、实验问题:1、算法分析题2-3:设a[0:n-1]是已排好序的数组。

请改写二分搜索算法,使得当搜索元素x不在数组中时,返回小于x的最大元素位置i和大于x的最小元素位置j。

当搜索元素数组中时候,i与j相同,均为x在数组中的位置。

2、算法分析题2-11:设a[0:n-1]是有n个元素的数组,k(0=<k<=b-1)是一个非负整数。

试设计一个算法将子数组a[0:k-1]与a[k:n-1]换位。

三、实验内容:算法2-3分析:将数组中N个元素按照它已排好的顺序分成数量大概相同的两个部分,去a[n/2]与x进行比较,如果发现x=a[n/2],则查找的算法终止,将i=j赋值并返回;如果发现x=a[n/2],则继续查找,直到找出或者a[right]<a[left],此时则i=right,j=left并返回其值。

算法2-11分析:题目只要求将a[0:k-1]与a[k:n-1]中各个元素换位,但是没用说明哪个与哪个互换,因此我们可以将数组中各个元素与它后面第K个元素交换,一直到i=k-1.四、实验结果:算法2-3:int BinarySearch(int a[10],const int & x, int & i , int & j){int left =0;int right = 9;while (a[right]>=a[left]){int middle = (left + right )/2;if (x==a[middle]){i = j = middle;return 0;}if (x>a[middle]){left=middle+1;}else right = middle -1;}i=right;j=left;return 0;}算法2-11:void change(int n,int a[]){int i;int temp;for (i = 0;i<k-1;i++){temp =a[i];a[i]=a[i+k];a[i+k]=temp;}}五、问题及解决:1、“i=right;j=left;”的取值问题,开始显示的i与j值总是相反的,也就是在赋值的过程中除了问题。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

实验1 不同排序算法分析、设计与比较
一、 实验问题描述
给定一个可排序的n个元素序列(数字、字符或字符串),对它们按照非降序方式重新
排列。

二、 算法思想比较
1、 冒泡排序
在要排序的一组数中,对当前还未排好序的范围内的全部数,自上而下对相邻的两个数
依次进行比较和调整,让较大的数下沉,较小的往上冒。即:每当两相邻的数比较后发现它
们的排序与排序要求相反时,就将它们互换。
2、插入排序
将一个记录插入到已排序好的有序表中,从而得到一个新,记录数增1的有序表。即:
先将序列的第1个记录看成是一个有序的子序列,然后从第2个记录逐个进行插入,直至整
个序列有序为止。
3、归并排序
归并排序法是将两个(或两个以上)有序的表合并成一个新的有序表,即把待排序序列
分为若干个子序列,每个子序列是有序的。然后再把有序子序列合并为整体有序序列。
4、快速排序
选择一个基准元素,通常选择第一个元素或者最后一个元素,通过一趟排序将待排序的
记录分割成独立的两部分,其中一部分记录的元素值均比基准元素值小。另一部分记录的元
素值比基准值大。此时基准元素在其排好序后的正确位置,然后分别对这两部分记录用同样
的方法继续进行排序,直到整个序列有序。

三、 算法伪代码
1、 冒泡排序伪代码
2、 插入排序伪代码
3、 归并排序伪代码
4、 快速排序伪代码
四、 算法时间复杂性理论比较
算法分析项 冒泡排序 插入排序 归并排序 快速排序
问题规模参数 数组大小n 数组大小n 数组大小n 数组大小n
基本操作 比较、交换 比较、移动 比较 比较、交换
影响基本操作执行次数的因素 数组原始排列影响交换次数 原始排列影响比较移动次数 不受原始排列影响 原始排列影响比
较和交换次数
基本操作执行次数表达式或递推方程 1+2+…+n-1 最好情况下为
1+1+…+1;
最坏情况下为
1+2+…+n-1

T(n)=2T(n/2)+O(n) T(n)=2T(n/2)+O(n)

时间复杂性 O(n^2) O(n^2) O(n*log n) 最好O(n)
平均O(n*log n)
最坏O(n^2)
空间复杂性
O(1) O(1) O(n) O(log n)

五、 测试用例设计
1、测试用例设计原则
(1)每种排序多次测试,使用不同数据规模。
(2)让四种排序测试同一组数据,对比其执行时间。
2、 具体测试用例
使用文件读写,存放在“in.txt”文件之中。

六、 算法时间复杂性实验比较
1、 实验环境
PC的配置:

编程工具:CodeBlocks
2、 实验方法
根据各个排序算法的思想和伪代码,编写出相应的程序。

首先测试程序本身的正确性:使用多组小规模数据,测试四种排序是否正确将原来无序
数组正确排序为有序数组。
四种排序测试无误之后,分别进行时间复杂性分析。因为要使用大规模数据且测试结果
需要记录以备分析、拟合,所以采用文件读写方式。
读入数据:
输出测试结果:
测试数组使用随机数产生:

测试排序运行时间的办法:在C++中使用clock()函数:
由于在小规模情况下很多测试结果为零,因此考虑重复排序次数以达到放大效果,同时
舍去测试结果为0的数据,取有效次数的平均值。

3、 结果记录
(1) 冒泡排序和插入排序

对冒泡和插入排序排序分别采用10次重复和20次重复,测试结果如下,左边为10次
重复,右边为20次重复,三列数据分别表示数据规模,平均用时,有效次数:
使用excel拟合出两种排序再10次和20次重复下的趋势图:
(2) 归并排序和快速排序
由于在小规模(1万以下)案例下,归并和快速排序测试结果几乎全部为0,因此不得
不考虑使用超大规模案例:

拟合出的曲线如下:
七、 算法时间复杂性理论与实验结果比较与分析
1、算法复杂性理论与实验结果比较
实验结果表明:
(1) 同等规模下,快速排序和归并排序比冒泡排序和插入排序要快,随着问题规模的增
加,这种差异越来越明显。
(2) 冒泡排序和插入排序的时间复杂性确实呈现O(n^2)的复杂度
(3) 冒泡排序和插入排序时间复杂性都为O(n^2),但在大规模情况下,插入排序要比冒
泡排序要快,这与理论相符合,因为冒泡排序比较的次数是固定的,但插入排序比
较的次数与原数组的输入密切相关,平均情况下比较次数没有冒泡排序多。
(4) 快速排序和归并排序时间复杂性都是O(n*log n),但在大规模情况下,快速排序要比
归并排序要快,理论分析上,归并排序复制数组占用大量的时间,而快速排序没有
这个操作,实验结果印证了这一分析。
2、理论与实验差距分析
快速排序和归并排序拟合出的效果几乎是线性的,我认为这与有效的测试用例太少有
关,实验的偶然性增加。同时,经过数学推导,当n比较大事,扩大k倍的数据规模,时间
复杂性扩大的规模近似为k倍,这也解释了为什么拟合出的曲线类似线性增长。

八、 问题思考与总结
1、对不同算法思想的理解
冒泡排序:从列表的第一个数字到倒数第二个数字,逐个检查:若某一位上的数字大于
他的下一位,则将它与它的下一位交换。
插入排序:每步将一个待排序的记录,按其顺序码大小插入到前面已经排序的字序列的
合适位置,直到全部插入排序完为止。归并排序:
归并排序:归并排序法是将多个有序表合并成一个新的有序表,即把待排序序列分为若
干个子序列,每个子序列是有序的。然后再把有序子序列合并为整体有序序列。
快速排序:先保证列表的前半部分都小于后半部分,然后分别对前半部分和后半部分排
序。
2、对不同算法程序结构的总结
冒泡排序使用两层循环,第一层确定冒泡的规模,表示已经排好的数据的个数,因为最
后几个数据已经沉底;第二层让选出的数据进行冒泡,只要前者比后者大,交换。
插入排序外层也是一个循环,表示待插入的那个数的位置,内部是一个不定循环,确定
这个数应插入的位置。
归并排序使用分治策略,把待排序的数组一分为二,采用递归结构,最后在合并数组。
快速排序的结构与归并排序类似,也采用分治策略和递归结构,但分完以后无需合并数
组,比归并排序简洁。

九、 实验出现的问题与解决
一开始数组开在函数之中,当数组长度超过一定规模就会导致内存溢出,因此把测试用
的数组设为全局变量。

相关文档
最新文档