算法设计与分析报告所有程序Word格式文档下载.docx
- 文档编号:20186811
- 上传时间:2023-01-17
- 格式:DOCX
- 页数:86
- 大小:45.22KB
算法设计与分析报告所有程序Word格式文档下载.docx
《算法设计与分析报告所有程序Word格式文档下载.docx》由会员分享,可在线阅读,更多相关《算法设计与分析报告所有程序Word格式文档下载.docx(86页珍藏版)》请在冰豆网上搜索。
//产生list[k:
m]的所有排列
//m是最后一个元素在数组中的下标
voidPerm(intlist[],intk,intm)
if(k==m)//如果只有一个元素
{
for(inti=0;
i<
=m;
i++)
printf("
%d"
list[i]);
printf("
\n"
}else
for(inti=k;
{
Swap(list[i],list[k]);
Perm(list,k+1,m);
//将元素还原
}
}
inta[5]={1,2,3,4,5};
//求数组前面三个元素的全排列
Perm(a,0,3);
4、用递归思想求整数划分问题
王晓东版——《计算机算法设计与分析(第四版)》P14页,例2-5
整数划分问题是算法中的一个经典命题之一,有关这个问题的讲述在讲解到递归时基本都将涉及。
所谓整数划分,是指把一个正整数n写成如下形式:
n=m1+m2+……+mi;
(其中mi为正整数,并且1<
=mi<
=n),则{m1,m2,...,mi}为n的一个划分。
如果{m1,m2,...,mi}中的最大值不超过m,即max(m1,m2,...,mi)<
=m,则称它属于n的一个m划分。
这里我们记n的m划分的个数为f(n,m);
例如,但n=4时,他有5个划分,{4},{3,1},{2,2},{2,1,1},{1,1,1,1};
注意4=1+3和4=3+1被认为是同一个划分。
该问题是求出n的所有划分个数,即f(n,n)。
下面我们考虑求f(n,m)的方法;
根据n和m的关系,考虑以下几种情况:
(1)当n=1时,不论m的值为多少(m>
0),只有一种划分即{1};
(2)当m=1时,不论n的值为多少,只有一种划分即n个1,{1,1,1,...,1};
(3)当n=m时,根据划分中是否包含n,可以分为两种情况:
(a).划分中包含n的情况,只有一个即{n};
(b).划分中不包含n的情况,这时划分中最大的数字也一定比n小,即n的所有(n-1)划分。
因此f(n,n)=1+f(n,n-1);
(4)当n<
m时,由于划分中不可能出现负数,因此就相当于f(n,n);
(5)但n>
m时,根据划分中是否包含最大值m,可以分为两种情况:
(a).划分中包含m的情况,即{m,{x1,x2,...,xi}},其中{x1,x2,...,xi}的和为n-m,可能再次出现m,因此是(n-m)的m划分,因此这种划分个数为f(n-m,m);
(b).划分中不包含m的情况,则划分中所有值都比m小,即n的(m-1)划分个数为f(n,m-1);
因此f(n,m)=f(n-m,m)+f(n,m-1);
综合以上情况,我们可以看出,上面的结论具有递归定义特征,其中
(1)和
(2)属于回归条件,(3)和(4)属于特殊情况,将会转换为情况(5)。
而情况(5)为通用情况,属于递推的方法,其本质主要是通过减小m以达到回归条件,从而解决问题。
其递推表达式如下:
f(n,m)=1;
(n=1orm=1)
f(n,m)=f(n,n);
(n<
m)
f(n,m)=1+f(n,m-1);
(n=m)
f(n,m)=f(n-m,m)+f(n,m-1);
(n>
因此我们可以给出求出f(n,m)的递归函数代码如下。
//求整数n的全部划分数,其中max代表最大加数
longGetPartitionCount(intn,intmax)
if(n==1||max==1)
return1;
elseif(n<
max)
returnGetPartitionCount(n,n);
elseif(n==max)
return1+GetPartitionCount(n,max-1);
returnGetPartitionCount(n,max-1)+GetPartitionCount(n-max,max);
请输入要划分的整数\n"
intn;
%d"
intnum=GetPartitionCount(n,n);
总划数为:
%d\n"
num);
怎样求出具体的划分结果呢?
这个问题比较难解决,等进一步分析。
5、用递归思想求汉诺塔问题
//n代表盘子个数
//a,b,c代表柱子名称
//程序功能:
将n个从小到大又叠放的盘子,从A柱子移动到B柱子,
//中间可以借助C柱子
voidHanoi(intn,charA,charB,charC)
if(n>
0)
Hanoi(n-1,A,C,B);
%d,%c-->
%c\n"
n,A,B);
//模拟移动过程
Hanoi(n-1,C,B,A);
Hanoi(3,'
a'
'
b'
c'
6、用递归思想实现插入排序
stdlib.h>
time.h>
voidinsertSort(int*aa,intn)
n=n-1;
insertSort(aa,n);
inta=aa[n];
intk=n-1;
while((k>
=0)&
&
a<
aa[k])
aa[k+1]=aa[k];
k--;
aa[k+1]=a;
inta[10];
srand((unsignedint)time(NULL));
for(inti=0;
10;
a[i]=rand()%100;
a[i]);
insertSort(a,10);
for(i=0;
7、用分治思想实现二分查找
方法一:
用到了递归
//在a数组里查找是否存在x这个元素,如果存在,则返回元素所在下标,如果不存在
//left:
查找的起始下标right:
查找的终止下标
intBinarySearch(inta[],intx,intleft,intright)
intmiddle=(left+right)/2;
if(left>
right)
return-1;
if(x==a[middle])
returnmiddle;
if(x>
a[middle])
returnBinarySearch(a,x,middle+1,right);
else
returnBinarySearch(a,x,left,middle-1);
inta[9]={-2,2,7,9,19,21,34,65,98};
intindex=BinarySearch(a,100,8);
index);
方法二:
用循环代替递归
//则返回-1
//n为最后一个元素的下标
intBinarySearch(inta[],intx,intn)
intleft=0;
//开始需要查找元素的下标
intright=n-1;
//最后需要查找元素的下标
while(left<
=right)
intmiddle=(left+right)/2;
if(x==a[middle])
returnmiddle;
if(x>
left=middle+1;
else
right=middle-1;
return-1;
8、用分治法求两个大整数的乘法
最简单的方法,这里没有体现分治法的思想
intmain()
chara[100],b[100],s[202];
inti,j,g,t=0,k=0,temp;
请输入两个大整数,空格分隔\n"
%s%s"
a,&
b);
intm=strlen(a);
intn=strlen(b);
while(k<
m+n-2)
s[k]=0;
temp=0;
for(i=0;
m;
for(j=0;
j<
n;
j++)
{
if((i+j)==k)//第k位上所有数字之和
temp+=(a[m-1-i]-48)*(b[n-1-j]-48);
}
g=(temp+t)%10;
t=(temp+t)/10;
//t用来保存进位
s[k]=g;
k++;
//求最高1位或者2位,并输出
temp=0;
for(j=0;
if((i+j)==k)
temp+=(a[m-1-i]-48)*(b[n-1-j]-48);
temp+=t;
//加上原来的进位
temp);
//将其它位逆向输出
for(i=m+n-2-1;
i>
=0;
i--)
s[i]);
return0;
9、用分治思想求一个数组的最大值与最小值
#defineLEN8
voidmaxmin(inta[],int*max,int*min,intlow,inthigh)
intmid,max1,min1,max2,min2;
if((high-low)<
if(a[high]>
=a[low])
*max=a[high];
*min=a[low];
}else
*max=a[low];
*min=a[high];
mid=(high+low)/2;
maxmin(a,&
max1,&
min1,low,mid);
max2,&
min2,mid+1,high);
*max=max1>
max2?
max1:
max2;
*min=min1<
min2?
min1:
min2;
inta[LEN];
intmax=-1,min=1000;
srand((unsigned)time(NULL));
数组里的元素为:
LEN;
maxmin(a,&
max,&
min,0,LEN-1);
\n最大值为:
%d\n最小值为:
max,min);
*/
10、用分法思想实现合并排序
#include<
intb[9];
voidmerge(intc[],intd[],intl,intm,intr)
inti=l,j=m+1,k=l;
while((i<
=m)&
(j<
=r))
if(c[i]<
=c[j])
d[k++]=c[i++];
d[k++]=c[j++];
//将剩余部分处理好
while(j<
=r)
while(i<
=m)
voidmergesort(inta[],intleft,intright)
if(left<
{
inti=(left+right)/2;
mergesort(a,left,i);
//将左边部分排好序
mergesort(a,i+1,right);
//将右边部分排好序
merge(a,b,left,i,right);
//将左右两边合并
for(intj=left;
=right;
a[j]=b[j];
inta[9]={4,3,6,8,9,1,25,2,34};
原始数据为:
9;
%d\t"
mergesort(a,0,8);
\n合并后的数据为:
11、用分治思想实现快速排序
voidquicksort(inta[],intp,intr)
{
intpartition(inta[],intp,intr);
if(p<
r)//不止一个元素时
intq=partition(a,p,r);
quicksort(a,p,q-1);
quicksort(a,q+1,r);
//以a[p]为基准,将数组a[p]-a[r]段元素分为两部,其实一部分
//比a[p]小,另一部分比a[p]大,
//返回值为a[p]最终所在位置
intpartition(inta[],intp,intr)
voidswap(int*x,int*y);
inti=p,j=r+1;
intx=a[p];
while(true)
while(a[++i]<
x&
i<
r);
while(a[--j]>
j>
p);
if(i>
=j)
break;
swap(&
a[i],&
a[j]);
a[p]=a[j];
a[j]=x;
returnj;
voidswap(int*x,int*y)
intt;
t=*x;
*x=*y;
*y=t;
inta[9]={9,8,7,6,5,4,3,2,1};
\n排序前的结果\n"
quicksort(a,0,8);
\n排序后的结果\n"
for(i=0;
如果每次划分不以a[p]为基准,而是随机从a[p]-a[r]里取一个数为基准,则可以设计如下随机化快速排序算法。
//随机选择策略的划分算法,需要调用partition函数
intRandomizedPartition(inta[],intp,intr)
inti=p+rand()%(r-p+1);
swap(&
a[p]);
returnpartition(a,p,r);
12、用分治法实现线性时间选择问题
本算法要用到上面快速排序的随机划分算法
intRandomizedSelect(inta[],intp,intr,intk)
if(p==r)//如果只剩下一个数,则这个肯定就是第k小的数
returna[p];
inti=RandomizedPartition(a,p,r);
//经过快速排序进行划分
intj=i-p+1;
//计算通过划分后,从a[p]到a[i]有多少数
if(k<
=j)//第k小的数在a[i]的前半段
returnRandomizedSelect(a,p,i,k);
else//第k小的数在a[i]的后半段,并且从a[p]到a[i]这些数都小于第k小的数
returnRandomizedSelect(a,i+1,r,k-j);
13、用分法思想实现残缺棋盘问题
王晓东版——《计算机算法设计与分析(第四版)》P20页,例2.6
注意:
同一种形状的骨牌,在填充时数字不一样,关键看三个相同数字摆放位置所构成的形状。
inttile=1;
//L型骨牌的编号(递增)
intboard[100][100];
//棋盘
/*****************************************************
*tr--当前棋盘左上角的行号
*tc--当前棋盘左上角的列号
*dr--当前特殊方格所在的行号
*dc--当前特殊方格所在的列号
*size:
当前棋盘的:
2^k
*****************************************************/
voidchessBoard(inttr,inttc,intdr,intdc,intsize)
if(size==1)//棋盘方格大小为1,说明递归到最里层
return;
intt=tile++;
//每次递增1
ints=size/2;
//棋盘中间的行、列号(相等的)
//检查特殊方块是否在左上角子棋盘中
if(dr<
tr+s&
dc<
tc+s)//在
chessBoard(tr,tc,dr,dc,s);
else//不在,将该子棋盘右下角的方块视为特殊方块
board[tr+s-1][tc+s-1]=t;
chessBoard(tr,tc,tr+s-1,tc+s-1,s);
dc>
=tc+s)//在
chessBoard(tr,tc+s,dr,dc,s);
else//不在,将该子棋盘左下角的方块视为特殊方块
board[tr+s-1][tc+s]=t;
chessBoard(tr,tc+s,tr+s-1,tc+s,s);
//检查特殊方块是否在左下角子棋盘中
if(dr>
=tr+s&
chessBoard(tr+s,tc,dr,dc,s);
else//不在,将该子棋盘右上角的方块视为特殊方块
board[tr+s][tc+s-1]=t;
chessBoard(tr+s,tc,tr+s,tc+s-1,s);
//检查特殊方块是否在右下角子棋盘中
=tc+s)
chessBoard(tr+s,tc+s,dr,dc,s);
else
board[tr+s][tc+s]=
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 算法 设计 分析 报告 所有 程序