用分治法解决快速排序问题及用动态规划法解决最优二叉搜索树问题及用回溯法解决图的着色问题一、课程设计目的:《计算机算法设计与分析》这门课程是一门实践性非常强的课程,要求我们能够将所学的算法应用到实际中,灵活解决实际问题。通过这次课程设计,能够培养我们独立思考、综合分析与动手的能力,并能加深对课堂所学理论和概念的理解,可以训练我们算法设计的思维和培养算法的分析能力。二、课程设计内容:1、分治法:(2)快速排序;2、动态规划:(4)最优二叉搜索树;3、回溯法:(2)图的着色。三、概要设计:分治法—快速排序:分治法的基本思想是将一个规模为n的问题分解为k个规模较小的子问题,这些子问题互相独立且与原问题相同。递归地解这些子问题,然后将各个子问题的解合并得到原问题的解。分治法的条件:(1)该问题的规模缩小到一定的程度就可以容易地解决;(2)该问题可以分解为若干个规模较小的相同问题,即该问题具有最优子结构性质;(3)利用该问题分解出的子问题的解可以合并为该问题的解;(4)该问题所分解出的各个子问题是相互独立的,即子问题之间不包含公共的子子问题。抽象的讲,分治法有两个重要步骤:(1)将问题拆开;(2)将答案合并;动态规划—最优二叉搜索树:动态规划的基本思想是将问题分解为若干个小问题,解子问题,然后从子问题得到原问题的解。设计动态规划法的步骤:(1)找出最优解的性质,并刻画其结构特征;(2)递归地定义最优值(写出动态规划方程);(3)以自底向上的方式计算出最优值;(4)根据计算最优值时得到的信息,构造一个最优解。回溯法—图的着色回溯法的基本思想是确定了解空间的组织结构后,回溯法就是从开始节点(根结点)出发,以深度优先的方式搜索整个解空间。这个开始节点就成为一个活结点,同时也成为当前的扩展结点。在当前的扩展结点处,搜索向纵深方向移至一个新结点。这个新结点就成为一个新的或节点,并成为当前扩展结点。如果在当前的扩展结点处不能再向纵深方向移动,则当前的扩展结点就成为死结点。换句话说,这个节点,这个结点不再是一个活结点。此时,应往回(回溯)移动至最近一个活结点处,并使这个活结点成为当前的扩展结点。回溯法即以这种工作方式递归的在解空间中搜索,直到找到所要求的解或解空间中以无活结点为止。四、详细设计与实现:分治法—快速排序快速排序是基于分治策略的另一个排序算法。其基本思想是,对于输入的子数组rpa:,按以下三个步骤进行排序:(1)、分解(divide)以元素pa为基准元素将rpa:划分为三段1:qpa,qa和,rqa:1使得1:qpa中任何一个元素都小于qa,而rqa:1中任何一个元素大于等于qa,下标在划分过程中确定。(2)、递归求解(conquer)通过递归调用快速排序算法分别对1:qpa和rqa:1进行排序。(3)、合并(merge)由于1:qpa和rqa:1的排序都是在原位置进行的,所以不必进行任何合并操作就已经排好序了。算法实现题:现将数列{2321344565768646303989202384738545940}进行快速排序。源程序如下:#includeiostreamusingnamespacestd;#definesize20intpartition(intdata[],intp,intr){intn=data[p],i=p+1,j=r,temp;//将n的元素交换到左边区域//将n的元素交换到右边区域while(true){while(data[i]n)++i;while(data[j]n)--j;if(i=j)break;temp=data[i];data[i]=data[j];data[j]=temp;}data[p]=data[j];data[j]=n;returnj;}voidquick_sort(intdata[],intp,intr){if(p=r)return;intq=partition(data,p,r);quick_sort(data,p,q-1);//对左半段排序quick_sort(data,q+1,r);//对右半段排序}intmain(){inti,n,data[size];printf(请输入要排列的数目(=20):);scanf(%d,&n);printf(请输入要排列的数列:\n);for(i=0;in;++i)scanf(%d,&data[i]);quick_sort(data,0,n-1);printf(排列后的数列为:\n);for(i=0;in;++i)printf(%d,data[i]);printf(\n);return0;}运行结果如下:图1动态规划—最优二叉搜索树1、最优二叉搜索树问题描述和分析:设nxxxS,,,21是有序集,且nxxx21,表示有序集S的二叉搜索树利用二叉树的结点存储有序集中的元素。它具有下述性质:存储于每个结点中的元素x大于其左子树中任一结点所存储的元素,小于其右子树中任一结点所存储的元素。二叉树的叶结点是形如1,iixx的开区间,在表示S的二叉搜索树中搜索元素x,返回的结果有两种情况:(1)在二叉搜索树的内结点中找到ixx。(2)在二叉搜索树的叶结点中确定1,iixxx。设在第(1)中情形中找到元素ixx的概率为;在第(2)种情形中确定1,iixxx的概率为。其中约定10,nxx。显然有:;1,0;0,0njbniaji110njjniibannababa,,,,,110称为集合S的存取概率分布。在表示S的二叉搜索树T中,设存储元素的结点深度为;叶结点1,jjxx的结点深度为,则:njjjiniidacbp011表示在二叉搜索树T中进行一次搜索所需要的平均比较次数,p又成为二叉搜索树T的平均路长。在一般情况下,不同的二叉搜索树的平均路长是不相同的。最优二叉搜索树问题是对于有序集S及其存取概率分布nnababa,,,,,110,在所有表示有序集S的二叉搜索树中找到一棵具有最小平均路长的二叉搜索树。2、最优子结构性质:二叉搜索树T的一棵含有结点jixx,,和叶结点11,,,,jjiixxxx的子树可以看作是有序集jixx,,关于全集合11,,jixx的一棵二叉搜索树,其存取概率为以下的条件概率:jkiwbbijkk/jhiwaaijhh1/式中,njiabbawjjiiij1,1。设是有序集jixx,,关于存取概率jjiiabba,,,,1的一棵最优二叉搜索树,其平均路长为。的根结点存储元素。其左右子树和的平均路长分别为和。由于和中结点深度是它们在中的结点深度减1,故有:rjmlmijijijipwpwwpw,11,,,,由于是关于集合1,,mixx的一棵二叉搜索树,故1,milpp。若1,milpp,则用1,miT替换可得到平均路长比更小的二叉搜索树。这与是最优二叉搜索树矛盾。故是一棵最优二叉搜索树。同理可证也是一棵最优二叉搜索树。因此最优二叉搜索树问题具有最优子结构性质。3、递归计算最优值:最优二叉搜索树的平均路长为,则所求的最优值为np,1。由最优二叉搜索树问题的最优子结构性质可建立计算的递归式如下:jipwpwwpwjkjkkikijkijijiji,,1,11,1,,,,min初始时,nipii1,01,。记jijipw,,为jim,,则nnnppwnm,1,1,1,1为所求的最优值。计算jim,的递归式为:jijkmkimwjimjkiji,,11,,min,niiim1,01,据此,可设计出解最优二叉搜索树问题的动态规划算法。算法实现题:给出标识符集{1,2,3}={do,if,stop}存取概率,若b1=0.4b2=0.2b3=0.05a0=0.2a1=0.05a2=0.05a3=0.05构造一棵最优二叉搜索树源程序如下:#includeiostreamusingnamespacestd;voidOptimalBinarySearchTree(floata[],floatb[],intn,floatm[][20],ints[][20],floatw[][20]){//求解最优值的方法inti,r,k;floatt;for(i=0;i=n;i++){w[i+1][i]=a[i];//搜索不到的点,最优解为0m[i+1][i]=0;}for(r=0;rn;r++)for(i=1;i=n-r;i++){intj=i+r;//左子树为空w[i][j]=w[i][j-1]+a[j]+b[j];m[i][j]=m[i+1][j];s[i][j]=i;for(k=i+1;k=j;k++){t=m[i][k-1]+m[k+1][j];if(tm[i][j]){//以k为根节点,左子树不为空m[i][j]=t;s[i][j]=k;}}m[i][j]+=w[i][j];}for(i=1;i=n;i++)for(intj=1;j=n;j++)couts[i][j]=s[i][j]endl;}voidprint(inti,intj,ints[][20],intS[])//递归输出结果{if(j=i){intk=s[i][j];cout(;print(i,k-1,s,S);cout);coutS[k];cout(;print(k+1,j,s,S);cout);}}intmain(){//主函数intn,i;floata[20],b[20],m[20][20],w[20][20];ints[20][20],S[20];cout请输入有序集元素的个数n:endl;cinn;cout请输入有序集各元素的值S[i](一共n个):endl;for(i=1;i=n;i++)cinS[i];cout请输入概率数组a的各元素的值a[i](一共n+1个):endl;for(i=0;i=n;i++)cina[i];cout请输入概率数组b的各元素的值b[i](一共n个):endl;for(i=1;i=n;i++)cinb[i];OptimalBinarySearchTree(a,b,n,m,s,w);cout最优值即平均步长为:m[1][n]endl;}运行结果如下:图2回溯法—图的着色1、图的m着色问题描述:给定无向连通图G和m种不同的颜色。用这些颜色为图G的各顶点着色,每个顶点着一种颜色。是否有一种着色法使G中每条边的2个顶点着不同颜色。这个问题是图的m可着色判定问题。若一个图最少需要m种颜色才能使图中每条边连接的2个顶点着不同颜色,则称这个数m为该图的色数。求一个图的色数m的问题称为图的m可着色优化问题。2、算法设计:一般连通图的可着色法问题并不仅限于平面图。给定图EVG,和m种颜色,如果这个图不是m可着色,则给出否定答案;如果这个图是m可着色的,找出所有不同的着色方法下面根据回朔法的递归描述框架Backtrack设计图的m着色算法。用图的邻接矩阵a表示无向量连通图EVG,。若ji,属于图EVG,的边集E,则1jia,否则0jia。整数1,2,…,m用来表示m种不同颜色。顶点所有颜色用表示,数组nx:1是问题的解向量。问题的解空间可表示为一棵高度为n+1的完全m叉树。解空间树的第nii1层中每一结点都有m个儿子,每个儿子相应于的m个可能的着色之一。第n+1层结点均为叶结点。在下面的解图的m可着色问题的回溯法中,iBacktrack搜索