分享
 
 
 

小话递归

王朝delphi·作者佚名  2006-01-09
窄屏简体版  字體: |||超大  

0:几种数学式的定义:

Fibonacci数列:

function Fibonacci(n:integer):integer;

begin

if n<1 then result:=1

else result:=Fibonacci(n-1)+Fibonacci(n-2)

end;

阶乘,

function RankMulti(n:integer):integer;

begin

if n<1 then result:=1

else result:=RankMulti(n-1)*n

end;

Ackerman函数:(变态的老外什么都想的出来)

function Ackerman(n,m:integer):integer;

begin

result:=0;

if (n=1) and (m=0) then result:=2

else

if (n=0) and( m>=1) then result:=1

else

if (n>=2) and(m=0) then result:=n+2

else

if (m>=1) and (n>=1) then result:=Ackerman(Ackerman(n-1,m),m-1)

end;

具体的意义我就不罗嗦了,就是个定义而已。涉及到解题思路,就与上面的直接表示略有不同,书上一般都叫作分治法。就是把大问题划分成n个子问题,再用同样的方法去解决..这个东西已经被人们讲烂了,我在讲的话大家要扔砖头了

递归的效率使得人们对他的评价褒贬不一。思路清晰使得性能下降其实也算是某种意义上的平衡。不过如果你去考试的话,一般没有很便宜的事情让你用分治法设计一个算法了事。而时间复杂度是必要考虑的,一般情况下要控制在O(n^2)之内.递归的时间复杂度可以用递归方程式求出来。一般情况下,在你的递归式之外的操作时间在O(n)之内的话,可以用递归式内的线性长度为底求递归次数的对数来估计时间复杂度。

比如:阶乘的递归式很快,是个线性时间,而Fibonacci数列则是T(n)=T(n-1)+T(n-2)+O(1)的操作,也就是T(n)=2T(n)+O(1),由递归方程式可以知道他的复杂度T(n)是O(n^2)

有关复杂性分析可以参考http://algorithm.myrice.com/algorithm/complexity/chapter6.htm

本文用到的是方法3套用公式,其中的=可以改写为<=或<,对于复杂度分析我们总是考虑最坏情况(有些随机算法除外),所以不管写只是个表达方法,本质都是一样的。

其实对于复杂度了解清楚就不要总害怕他的低效率了,因为它的复杂度也不总是传说中的指数级。

另外用堆栈改写是不能降低复杂度。

有些算法是不能用一系列O(1)的算法来迭代改写的。

下面是几个分治算法的例子,全部模拟最初的解题思路来递归实现,未经优化。作为抛砖引玉。

==========================={CopyRight jinjazz}==========

1.求正整数划分的个数:求一个正整数划分为一系列正整数之和有多少不同的划分方法 比如6有11种

function DivInteger(n:integer):integer;

function DivMax(n,m:integer):integer; //求最大子数不大于m的划分个数

begin

result:=0;

if (m=1) or (n=1) then result:=1

else

if m>n then result:=DivMax(n,n)

else

if m=n then result:=1+DivMax(n,n-1)

else

if (n>m) and (M>1) then result:=divMax(n,m-1)+DivMax(n-m,m)

end;

begin

result:=DivMax(n,n)

end;

=========================={CopyRight jinjazz}=============

2.求全排列(定义:var PermVar:array[0..4] of Variant; 初始化时可以附任何类型的值)

procedure Perm(var JtVariant:array of Variant;k,m:integer;jtList:Tstrings);

var i:integer;

procedure swap(var a,b:Variant);

var tmp:Variant;

begin

tmp:=a;

a:=b;

b:=tmp;

end;

begin

if k<=m then

for i:=k to m do

begin

swap(JtVariant[k],JtVariant[i]);

Perm(JtVariant,k+1,m,JtList);

swap(JtVariant[k],JtVariant[i]);

end

else

begin

jtList.Add('Perm:');

for i:=0 to m do

jtList.Add(JtVariant[i]);

jtList.Add('==================')

end;

end;

//建议针对不同类型相应的将variant替换掉

============================={CopyRight jinjazz}=========

3.汉诺塔(虽然经常见但是有多少人亲手写过?)

procedure hanoi(n:integer;p1,p2,p3:char;JtList:Tstrings); //个数,盘子标志,输出

procedure move(m:integer;ps,pd:char);

begin

JtList.Add(inttostr(m)+ ' from '+ ps+' to '+pd);

end;

begin

if n>0 then

begin

hanoi(n-1,p1,p3,p2,JtList);

move(n-1,p1,p2);

hanoi(n-1,p3,p2,p1,JtList);

end;

end;

//hanoi(3,'a','b','c',memo1.Lines)

==============================={CopyRight jinjazz}========

4.快速排序法

procedure QuickSort(var SortNum:array of integer;p,r:integer);

procedure swap(var a,b:integer); //交换

var tmp:integer;

begin

tmp:=a;

a:=b;

b:=tmp;

end;

function partition(var SortNum:array of integer;p,r:integer):integer; //划分

var i,j,x:integer;

begin

i:=p;j:=r+1;

x:=SortNum[p];

while true do

begin

repeat inc(i)

until SortNum[i]<x;

repeat inc(j,-1)

until SortNum[j]>x;

if i>=j then break;

swap(SortNum[i],SortNum[j]);

end;

SortNum[p]:=SortNum[j];

SortNum[j]:=x;

result:=j;

end;

var q:integer;

begin

if p<r then

begin

q:=partition(SortNum,p,r);

QuickSort(SortNum,p,q-1);

QuickSort(SortNum,q+1,r);

end;

end;

=============================={CopyRight jinjazz}==

5.二分查找法.对已排序序列进行查找

function BinarySearch(SearchNum:array of integer;x,n:integer):integer;//序列,值,序列长度

var left,right,mid:integer;

begin

result:=-1;

left:=0;right:=n-1;

while(left<=right)do

begin

mid:=(left+right) div 2;

if x=SearchNum[mid] then

begin

result:=mid;

exit;

end;

if x>SearchNum[mid] then left:=mid+1

else right:=mid-1

end;

end;

=============================={CopyRight jinjazz}=========

6.无限位大整数加法(当然有更简便的方法,但这只是个分治法解决问题的思路)

function InfiniteAdd(a,b:string):string;

var a1,a2,b1,b2,M,D:string;

i,k:integer;

begin

if length(a)<length(b) then

for i:=1 to length(b)-length(a) do a:='0'+a

else for i:=1 to length(a)-length(b) do b:='0'+b;

if length(a)<=18 then //int64最大19位,保证不溢出

result:=inttostr(strtoint64(a)+strtoint64(b))

else

begin

k:=length(a) div 2;

a1:=copy(a,1,k);a2:=copy(a,k+1,length(a)-k);

b1:=copy(b,1,k);b2:=copy(b,k+1,length(b)-k);

M:=InfiniteAdd(a2,b2);

D:=InfiniteAdd(a1,b1);

if length(M)>length(a2) then

result:=InfiniteAdd(D,'1')+copy(M,2,length(M)-1)

else

begin

if length(M)<length(a2) then

for i:=1 to length(a2)-length(M) do M:='0'+M;

result:=D+M;

end;

end;

end;

============================{CopyRight jinjazz}===============

7.无限位大整数整除2(模拟递归过程,没经过优化)

function InfiniteDiv2(s:string):string; //这是个O(n)的计算 :-)

var i,k,w:integer;

s1,s2,D1,D2:string;

begin

if length(s)<=17 then

begin

result:=inttostr(strtoint64(s)div 2);

end

else

begin

k:=length(s) div 2;

s1:=copy(s,1,k);s2:=copy(s,k+1,length(s)-k);

D1:=InfiniteDiv2(s1);

D2:=InfiniteDiv2(s2);

if length(D2)<k then

for i:=1 to k-length(D2)+1 do D2:='0'+D2;

if byte(s1[length(s1)])mod 2=1 then

D2:=inttostr(strtoint(D2[1])+5)+copy(D2,2,length(D2)-1);

result:=D1+D2;

end;

end;

=========================={CopyRight jinjazz}======

8.无限位数乘法 (模拟递归过程,没经过优化)

function InfiniteMulti(a,b:string):string; //时间复杂度有点高

var a1,a2,b1,b2,U,V,X,Y:string;

i,k:integer;

begin

if length(a)<length(b) then

for i:=1 to length(b)-length(a) do a:='0'+a

else for i:=1 to length(a)-length(b) do b:='0'+b;

//a*b=a1*b1(补0)+a1*b2(补0)+a2*b1(补0)+a2*b2 不能超过9位

if length(a) mod 2=1 then

begin

a:='0'+a;

b:='0'+b;

end;

if length(a)<=9 then //int64最大19位,保证不溢出

result:=inttostr(strtoint64(a)*strtoint64(b))

else

begin

k:=length(a) div 2;

a1:=copy(a,1,k);a2:=copy(a,k+1,length(a)-k);

b1:=copy(b,1,k);b2:=copy(b,k+1,length(b)-k);

U:=InfiniteMulti(a1,b1);

V:=InfiniteMulti(a1,b2);

X:=InfiniteMulti(a2,b1);

Y:=InfiniteMulti(a2,b2);

for i:=1 to k do

begin

U:=U+'00';

V:=V+'0';

X:=X+'0';

end;

result:=InfiniteAdd(U,V);

result:=InfiniteAdd(result,X);

result:=InfiniteAdd(result,Y);

end;

end;

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有