我用的是人民邮电出版社的数据结构。
书上刚开始给了阶乘和fibonacci的算法,没什么可说的。接下来给了个算法分析,这个很有意思。
意思是:把下面这个输出出来:
1
22
333
4444
55555
这并不难,代码是:
#include<stdio.h>
void display(int n)
{
if(n!=0)
{
display(n-1);//这里一定要注意,不是n- -(举个例子,n=5,n-1为4,n- -是5)这玩意特别难理解,尽量少用为好。
for(int i=0; i<n; i++)
{
printf("%d",n);
}
printf("\n");
}
}
int main()
{
int a;
scanf("%d",&a);
display(a);
return 0;
}
上面这个代码用到了递归的精髓,佩服佩服。
再往后,就是核心了,递归和非递归之间的转化,有简单和复杂的两类。简单的不解释,看的是智商,1+1不知道得几谁也没办法。复杂的引入了一个回溯(su)。
书上给的代码的意思是,举个例子:1 2 3 4 5 一共5个数,先输出中间的,也就3,之后分为左半部分和右半部分,左右部分都按照这个规则再输出中间的值,先左部分后右部分,输出结果为:3 1 2 4 5 。代码如下,递归的:
#include<stdio.h>
typedef struct list
{
int a[100];
int size;
}list;
void display(list stl,int l,int r)
{
int m;
if(l<=r)
{
m=(l+r)/2;
printf("%d ",stl.a[m]);//假如已经输出了3,左面是1和2,m=(1+2)/2=1,千万记住了,不是1.5
display(stl,l,m-1);
display(stl,m+1,r);
}
}
int main()
{
list stl;
stl.size=0;
for(int i=0; i<5; i++)
{
scanf("%d",&stl.a[i]);
stl.size=stl.size+1;
}
display(stl,0,stl.size-1);
return 0;
}
非递归的,代码是:
#include<stdio.h> //非递归
#include<stdlib.h>
typedef struct list
{
int a[100];
int size;
} list;
typedef struct
{
int l;
int r;
} stack;
void display(list stl,int l,int r)
{
if(l<=r)
{
stack stack[100];
int mid,top=0;
while(l<=r || top!=0)
{
if(l<=r)
{
mid=(l+r)/2;
printf("%d",stl.a[mid]);
stack[top].l=mid+1;
stack[top].r=r;
top=top+1;
r=mid-1;
}
else
{
top=top-1;
l=stack[top].l;
r=stack[top].r;
}
}
}
}
int main()
{
list stl;
stl.size=0;
for(int i=0; i<5; i++)
{
scanf("%d",&stl.a[i]);
stl.size=stl.size+1;
}
display(stl,0,stl.size-1);
return 0;
}
我认为,递归和非递归之间的转化最巧妙的地方就是在于,他们的方法是一样的,只不过是表达方式不一样罢了。在转换的过程中,非递归借助了栈来做第三者,这个和树的层次遍历有异曲同工之妙。
在接下来,是一个应用问题,背包:时间不够了,10天后再来变这段代码。