1、中南大学算法实验报告中南大学算法分析与设计实验报告班级: 物联网*班 学号: * 姓名: * 指导老师: 沙莎 2012年12月28日目 录分治法实验1.快速排序 22.归并排序43.最大最小值7动态规划实验多段图10回溯法实验 N皇后15 分治法实验 分治法的基本思想是将一个规模为n的问题分解为k个规模较小的子问题,这些子问题互相独立且与原问题相同。递归地求解这些子问题,然后将各子问题的解合并得到原问题的解。1.快速排序快速排序是基于分治策略的一个排序算法实现快速排序的分治过程如下:分解:数组Ap.r被划分为两个(可能空)子数组Ap.q-1和Aq+1.r,使得Ap.q-1中的每个元素都小于等
2、于A(q),而且,小于等于Aq+1.r中的元素。下标q也在这个划分过程中进行计算。解决:通过递归调用快速排序,对子数组Ap.q-1和Aq+1.r排序合并:因为两个子数组是就地排序的,将它们的合并不需要操作,整个数组Ap.r已排序。实验代码如下:#include using namespace std; int num; void swap(int &a, int &b) int temp = a; a = b; b = temp;/交换元素位置 void PrintArray(int *arr) for(int i=1; i=num; +i) cout arri ; cout endl; in
3、t Partition1(int *arr, int p, int r) int x=arrr; int i=p-1; int j; for(j=p;j=r-1;j+) if(arrj=x) i=i+1; swap(arri,arrj); swap(arri+1,arrr); return i+1;/对子数组Ap.r进行就地重排 void QuickSort(int *arr, int p, int r) if(p r) int q = Partition1(arr, p, r); QuickSort(arr, p, q-1); QuickSort(arr, q+1, r); /该过程实现快速
4、排序 int main() int arr100; cout num; cout 请输入元素大小:n; for(int i=1; i arri; QuickSort(arr, 1, num); cout 最后结果:; PrintArray(arr); return 0;运行结果如下图所示:实验收获与体会:通过证明可以得到该算法在最坏情况下的时间复杂性为T(n)=O(n2),平均情况下的时间复杂性是O(nlogn),通过该实验对分治法基本思想有了了解。2.归并排序:基本操作如下:分解:将n个元素分成各含n/2个元素的子序列解决:用合并排序法对两个子序列递归地排序合并:合并两个已排好序的子序列得到
5、排序结果在对子序列排序时,其长度为1时递归结束。单个元素被视为是已排好序的。实验代码如下:#include#includetemplatevoid Merge(T c,T d,int l,int m,int r)/把cl:m和cm:r归并到dl:r int i,j,k; i=l; /第一段游标 j=m+1; /第二段游标 k=l; /结束游标 while(i=m)&(j=r) if(cim)for(int q=j;q=r;q+) dk+=cq; else for (int q=i;q=m;q+) dk+=cq;templatevoid MergePass(T x,T y,int s,int n
6、) /归并大小为s的相邻的段 int i=0; while(i=n-2*s) /归并两个大小为s的相邻段 Merge(x,y,i,i+s-1,n-1); i=i+2*s; /剩下不足两个元素 if(i+sn)Merge(x,y,i,i+s-1,n-1); else for(int j=i;j=n-1;j+) /把最后一段复制到y yj=xj;templatevoid MergeSort(T a,int n)T* b=new Tn;int s=1;while(sn) MergePass(a,b,s,n); s+=s; MergePass(b,a,s,n); s+=s;int main() int
7、 n,i,j=0; double *Input; cout请输入您要排序的元素个数n; Input=new double100000;/定义排序数组 cout请输入您要排序的元素:endl; for(i=0;i*(Input+i); MergeSort(Input,n);/调用排序函数 cout排序后的数组元素为:endl; for(i=0;in;i+) coutInputi ; j+; if(j%10=0) coutendl; delete Input;/释放内存;运行结果如下图所示:实验收获与体会:通过归并排序的实验对分治法在排序中的应用有了更深刻的了解,与快速排序对比,归并排序相对较“稳
8、定”些。3.最大最小值问题: 每次将问题分成大致相等的两部分,分别在这两部分中找出最大值与最小值,再将这两个子问题的解组合成原问题的解,就可得到该问题的分治算法。算法描述:procedure MAXMIN(i, j, fmax, fmin)global n,A1:ncase ij: fmaxfminAi /*只有一个元素*/ ij-1:if Ai Aj) *max=Ai; *min=Aj; else *max=Aj; *min=Ai; return; mid=(i+j)/2; maxmin2( A, mid+1, j,&max2,&min2); maxmin2( A, i,mid,&max1,
9、&min1); if(max1max2) *max=max1; else *max=max2; if(min1min2) *min=min2; else *min=min1; main() int i,n; int AN; int max,min; printf(请输入要比较的数据的个数:); scanf(%d,&n); for(i=0;in;i+) printf(请输入第%d个数,i+1); scanf(%d,&Ai); maxmin2(A,0,n-1,&max,&min); printf(最大值为:%d 最小值为:%d,max,min);运行结果如下图所示:实验收获与体会:通过该实验对分治
10、法掌握的更加透彻,明白了分治法发挥的作用。 动态规划实验 对于一个多阶段过程问题,是否可以分段实现最优决策,信赖于该问题是否有最优子结构性质,能否采用动态规划的方法,还要看该问题的子问题是否具有重叠性质。 最优子结构性质:原问题的最优解包含了其子问题的最优解 子问题的重叠性质:每次产生的子问题并不总是新问题,有些子问题被反复计算多次。问题的最优子结构性质和子问题重叠性质是采用动态规划算法的两个基本要素 动态规划一般方法1.找出最优解的性质,并刻画其结构特征2.递归地定义最优值(写出动态规划方程)3.以自底向上的方式计算出最优值多段图多段图算法:Procedure FGRAPH(E,k,n,P)
11、/输入是按段的顺序给结点编号的,有n个结点的k段图。E是边集,c(i,j)是边的成本。P(1:k)是最小成本路径。/real COST(n),integer(n-1),P(k),r,j,k,nCOST(n)-0for j-n-1 to 1 by -1 do /计算COST(j)/设r是一个这样的结点,(j,r)E且使c(j,r)+COST(r)取最小值COST(j)- c(j,r)+COST(r);D(j)-r;Repeat /向前对j-1进行决策/P(1)-1; P(k)-n;for j-2 to k-1 do / 找路径上的第j个节点/ P(j)-D(P(j-1);repeat;end F
12、GRAPH实验代码如下:#include using namespace std;#define MAX 100 #define n 12 /图的总顶点数#define k 5 /图的段数int cnn;void init(int cost) /初始化图 int i,j; for(i=0;i13;i+) for(j=0;j13;j+) cij=MAX;/初始化每条边长度为MAX c12=9; c13=7; c14=3; c15=2; c26=4; c27=2; c28=1; c36=2; c37=7; c48=11; c57=11; c58=8; c69=6; c610=5; c79=4; c
13、710=3; c810=5; c811=6; c912=4; c1012=2;c1112=5; /给每条边赋值 void front(int cost,int path,int d) /向前递推算法求多段图的最短路径 int r,j,temp,min; for(j=0;j=1;j-) temp=0; min=cjtemp+costtemp; /初始化当前路径长度的最小值 for(r=0;r=n;r+) if(cjr!=MAX) if(cjr+costr)min)/找到最小的r,使 cjr+costr取最小值 min=cjr+costr; temp=r; costj=cjtemp+costtem
14、p; dj=temp; /向前对j-1进行决策 path1=1;/第一段所取节点 pathk=n;/最后一段所取节点 for(j=2;jk;j+) pathj=dpathj-1;/找到路径上第j个节点 void back(int bcost,int path1,int d) / 使用向后递推算法求多段图的最短路径 int r,j,temp,min; for(j=0;j=n;j+) bcostj=0; for(j=2;j=n;j+) temp=12; min=ctempj+bcosttemp; /初始化当前路径长度最小值 for(r=0;r=n;r+) if(crj!=MAX) if(crj+b
15、costr)=2;i-) path1i=dpath1i+1; /找出各段的节点 int main() int cur=-1; int j; int cost13,d12,bcost13; int pathk; int path1k; couttttt多段图问题endl; coutnn; init(cost); front(cost,path,d); cout向前递推算法求得的最短路径:nn; for(int i=1;i=5;i+) if(i=5) coutpathi; else coutpathi; coutn; coutendl最短路径:cost1endl; coutn; cout向后递推算
16、法求得的最短路径:nn; back(bcost,path1,d); for(j=1;j=5;j+) if(j=5) coutpathj; else coutpath1j; coutn; coutendl最短路径:bcost12endl; coutn; 运行结果如下图所示:实验收获与体会:通过多段图实验对动态规划的思想有了更深理解,动态规划与分治法类似,基本思想也是将待求解问题分成若干个子问题,但是分解得到的子问题往往不是互相独立的。 回溯法实验 回溯法在问题的解空间树中,按深度优先策略,从根结点出发搜索解空间树。算法搜索至解空间树的任意一点时,先判断该结点是否满足约束。如果不满足,则跳过对该结
17、点为根的子树的搜索,逐层向其祖先结点回溯;否则,进入该子树,继续按深度优先策略搜索。N皇后:基本思想: (1)针对所给问题,定义问题的解空间,使N个皇后不在同行同列,对角线上; (2)确定易于搜索的解空间结构;(3)以深度优先方式搜索解空间,并在搜索过程中用剪枝函数避免无效搜索。 实验代码如下:#include#include math.hclass QUEEN public: friend int nQueen(int); private: bool Place(int k); void Backtrack(int t); int n,*x; long sum;int nQueen(int
18、n) QUEEN x; x.n=n; x.sum=0; int *p=new int n+1; for(int i=0;i=n;i+) pi=0; x.x=p; x.Backtrack(1); deletep; return x.sum; bool QUEEN:Place(int k) for(int j=1;jn)sum+; cout n皇后问题的第sum个可行解的坐标为:endl; for(t=1;t=n;t+) cout ( t,xt)endl; cout *endl; else for(int i=1;i=n;i+) xt=i; if(Place(t) Backtrack(t+1);/递归求解 int main() int n; cout *N 皇后问题* endl; cout endl; cout 请输入皇后的个数 n: n; coutnQueen( n)endl; cout *N 皇后问题结束*endl; 运行结果如下图所示:实验收获与体会: 通过该实验对回溯法的思想有了较深的了解,通过亲手实践,加深了记忆与理解,该实验的算法也可以用在类似有关回溯法问题上。
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1