}
(3)代码运行结果
(4)时间复杂度
f(n)=f(n—1)+n—1=f(n—2)+n—1+(n+2)=n*(n-1)/2;
算法用于递归栈的工作单元数与n为同一数量级,即时间复杂度为O(n)
实验二递归算法的实现
•自然归并算法的设计与实现
•设计思路
首先讲待排序的n个元素分成大致相同的子集合,然后分别对这两个子集进行排序最后将排好序的子集合归并成所要求的排好序的集合
•源程序代码
#include〈stdio。
h>
#include〈iostream〉
usingnamespacestd;
#definemax10
voidMerger_Sort(inta[],intlow,inthigh)
{
inttemp[max];
if(low〈high)
{
intmid=(low+high)/2;
inti=low;
intj=mid+1;
intl=low;
Merger_Sort(a,low,mid);
Merger_Sort(a,mid+1,high);
while(i<=mid&&j〈=high)
{
if(a[i]〈a[j])
{
temp[l++]=a[i++];
}
else
{
temp[l++]=a[j++];
}
}
while(i〈=mid)
{
temp[l++]=a[i++];
}
while(j〈=high)
{
temp[l++]=a[j++];
}
for(i=low;i<=high;i++)
{
a[i]=temp[i];
}
}
}
voidmain()
{
inta[max];
intn;
cout<〈"请输入元素个数n:
";
cin〉>n;
cout〈〈"请输入"〈";
for(inti=0;i{
cin〉〉a[i];
}
Merger_Sort(a,0,n-1);
for(intj=0;j〈n;j++)
{
cout<〈a[j]〈〈”";
}
cout<}
(3)代码运行结果
(4)时间复杂度
自然规定排序算法的时间复杂度为:
O(n)。
•快速排序算法的设计与实现
•设计思路
基本思想是通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列
•源程序代码
#include〈iostream>
usingnamespacestd;
intPartition(inta[],intp,intr)
{
inti=p,j=r+1,sub;
intx=a[p];
while(true)
{
while(a[++i]while(a[—-j]〉x);
if(i>=j)break;
sub=a[i];
a[i]=a[j];
a[j]=sub;
}
a[p]=a[j];
a[j]=x;
returnj;
}
voidQuickSort(inta[],intp,intr)
{
if(p{
intq=Partition(a,p,r);
QuickSort(a,p,q—1);//对左半段排序
QuickSort(a,q+1,r);//对右半段排序
}
}
intmain()
{
inta[100];
intn;
cout〈〈"请输入数组元素个数n(0〈n<100):
”;
cin>>n;
cout〈〈"请输入数组元素:
";
for(inti=0;i{
cin〉〉a[i];
}
QuickSort(a,0,n-1);
for(intj=0;j〈n;j++)
{
cout〈〈a[j]<<"";
}
cout〈}
(3)代码运行结果
(4)时间复杂度
快速排序算法在最坏的情况下的运行时间是O(n^2).如果选取数组中的中值元素作为划分元素,那么快速排序算法的时间复杂度应为O(nlogn)。
此时快速排序算法的递归深度接近于logn。
因此,快速排序算法的的空间复杂度应为为O(logn)
实验三贪心算法的实现
1。
背包问题的设计与实现
(1)设计思路
将前i件物品放入容量为v的背包中”这个子问题,若只考虑第i件物品的策略(放或不放),那么就可以转化为一个只牵扯前i-1件物品的问题。
如果不放第i件物品,那么问题就转化为“前i-1件物品放入容量为v的背包中",价值为f[i-1][v];如果放第i件物品,那么问题就转化为“前i-1件物品放入剩下的容量为v—w[i]的背包中",此时能获得的最大价值就是f[i-1][v—w[i]]再加上通过放入第i件物品获得的价值v[i]。
注意f[v]有意义当且仅当存在一个前i件物品的子集,其费用总和为f[v]。
所以按照这个方程递推完毕后,最终的答案并不一定是f[N][V],而是f[N][0..V]的最大值
(2)源程序代码
#include〈iostream>
usingnamespacestd;
#definen3
structthing
{
floatp;
floatw;
floatv;
};
voidquick(thinga[],intb)
{
inti;
for(i=0;i{
a[i]。
v=a[i].p/a[i].w;
}
for(i=0;i〈n;i++)
{
for(intj=i+1;j〈n;j++)
{
if(a[i]。
v{
thingb;
b.v=a[i]。
v;
b.p=a[i].p;
b.w=a[i]。
w;
a[i].p=a[j]。
p;
a[i].v=a[j]。
v;
a[i].w=a[j]。
w;
a[j].p=b。
p;
a[j].v=b.v;
a[j].w=b。
w;
}
}
}
}
floatgreedy(floatM,thinga[],floatx[],intb)
{
floatm,p=0;
for(inti=0;i〈n;i++)
{
a[i].v=a[i].p/a[i].w;
x[i]=0;
}
quick(a,n);
m=M;
for(i=0;i〈n;i++)
{
if(a[i]。
w<=m)
{
x[i]=1;
m=m—a[i].w;
p=p+a[i].p;
}
else
{
x[i]=m/a[i]。
w;
p=p+x[i]*a[i].p;
break;
}
}
returnp;
}
voidmain()
{
inti;
cout<〈"输入三种物品的价格:
”<thinga[n];
for(i=0;i〈n;i++)
{
cin〉>a[i].p;
}
cout〈〈”输入三种物品的重量:
"〈〈endl;
for(i=0;i{
cin>〉a[i]。
w;
}
floatm=20;
floatx[n];
floatp=greedy(m,a,x,n);
cout<<”最佳解"<
}
•代码运行结果
(4)时间复杂度
背包问题算法的时间复杂度为O(n)
2。
单源点最短路径问题的设计与实现
(1)设计思路
将图G中所有的顶点V分成两个顶点集合S和T。
以v为源点已经确定了最短路径的终点并入S集合中,S初始时只含顶点v,T则是尚未确定到源点v最短路径的顶点集合。
然后每次从T集合中选择S集合点中到T路径最短的那个点,并加入到集合S中,并把这个点从集合T删除.直到T集合为空为止
(2)源程序代码
#include〈iostream〉
usingnamespacestd;
typedefstructadj_list{
intv_num;
floatlen;
structadj_list*next;
}NODE;
#defineMAX_FLOAT_NUM3.14e38f
#defineN50
voiddijkstra(NODEnode[],intn,intu,floatd[],intp[]){
floattemp;
inti,j,t;
bool*s=newbool[n];
NODE*pnode;
for(i=0;i{
d[i]=MAX_FLOAT_NUM;
s[i]=false;
p[i]=—1;
}
if(!
(pnode=node[u]。
next))
{
return;
}
while(pnode)
{
d[pnode->v_num]=pnode-〉len;
p[pnode—>v_num]=u;
pnode=pnode-〉next;
}
d[u]=0;s[u]=true;
for(i=1;itemp=MAX_FLOAT_NUM;
t=u;
for(j=0;j〈n;j++){
if(!
s[j]&&d[j]〈temp){
t=j;
temp=d[j];
}
}
if(t==u){//
break;
}
s[t]=true;
pnode=node[t]。
next;
while(pnode){
if(!
s[pnode->v_num]&&d[pnode-〉v_num]>d[t]+pnode-〉len){
d[pnode->v_num]=d[t]+pnode—〉len;
p[pnode-〉v_num]=t;
}
pnode=pnode-〉next;
}
}
deletes;
}
voidprintWay(inti,intp[])
{
if(p[i]==-1)return;
printWay(p[i],p);
cout〈<"-〉"<}
voidprintln()
{
cout〈<”--—--—-—-----—-----——--———----—-—-----—--——-——--”<}
intmain()
{
NODEnode[N];
floatd[N];
intp[N];
intn;
intu;
inti,v;
NODE*pnode;
cout〈<"请输入顶点个数:
";
cin>>n;
cout〈<"请输入源顶点u编号(0〈u<=”<〈n<〈”):
”;
cin>〉u;
u-—;
cout〈〈"请输入各个点到其他点的距离(输入顶点编号距离,编号输入0表示结束):
”〈〈endl;
for(i=0;i〈n;i++){
cout<<”顶点”〈〈char(65+i)〈<”:
”;
node[i]=*(newNODE);//创建新结点
node[i].v_num=i;
node[i].len=0;
node[i]。
next=NULL;
while(cin>>v&&v〉0){
pnode=newNODE;
pnode->v_num=v-1;
cin〉>(pnode->len);
pnode-〉next=node[i]。
next;
node[i]。
next=pnode;
}
}
dijkstra(node,n,u,d,p);
println();
for(i=0;i〈n;i++){
if(u==i||d[i]==MAX_FLOAT_NUM)continue;//
cout<”〈〈d[i]〈cout〈〈"路径:
"〈〈char(u+65);
printWay(i,p);
cout<println();
}
return0;
}
(3)代码运行结果
(4)时间复杂度
算法的时间主要消耗在将各种物品按照单位重量的价值从大到小的排序,因此,其时间复杂性为O(nlog2n)
实验心得
在计算机专业中,算法分析与设计是一门很重要的课程,很多人在编写程序的时候要依赖它,算法的学习对于培养一个人的逻辑思维能力有着极大的帮助,在一定程度上提高了我们思考分析及解决问题的能力。
如果一个算法有缺陷,或者该算法并不适合某个问题,执行这个算法,并不能解决这个问题。
不同的算法也会导致不同的时间,空间及效率来完成同样的问题,所以如何针对问题需求选择最合适的算法也需要我们日后深入学习.就目前来说,我们还不具备编写完整程序的能力,但是,我们现在最需要的是培养针对问题能迅速找准对应算法来解决问题的能力。
最后,此次算法的学习,我收获颇丰.