递归

递归算法采用了分而治之的思想,将复杂的问题分解为小的问题,并且这个小的问题的类型与原始问题的类型完全相同。通过分解,最终原始问题变得非常小,其解决方案显而易见,或为已知。那么对此类问题应怎样建立递归模型呢。

1,分析问题:确定问题能否分解为一个更小的问题,并且小的问题的类型和原始问题类型相同。确定该问题的循环不变式(loop invariant).

2,确定基例:当把问题分解的足够小时,即其最小问题的解决方案显而易见或者已知,即寻找到了此问题的基例。将基例作为解决问题的最小条件,由此条件而逐级回溯从而解决问题。
3,执行步骤:将一级小问题视为已知完全求解,则此原始问题的解决方案很容易确定,由此确定解决方案的执行步骤。
4,参数确定:递归函数的参数可分为四类:源因子,控制因子,接收因子和行为因子。具体问题具体分析,确定其需要的参数因子。
实例分析
hanoi塔
hanoi塔大家都已经熟知,在这里我就不多说了,直入正题。
初始状态时,所有的圆盘都在A上,目的是将A上的圆盘全部移到B上,那么将A上的n-1、n-2 个圆盘放在B上与将A上的所有的圆盘都放在B上类型相同,即可确定采用递归算法。当盘的数目为0或者为1时可确定达到基例,其无需进行操作或者将一个盘移到由A移到B上。将A盘上n-1个圆盘操作视为已完成的整体(即可一次性将其移到B或C盘)。完成原始问题的解决方案确定为,将A上n-1个圆盘移到C上,然后将A上的最后一个移到B上,然后再将C盘上的n-1个圆盘移到B上,则完成所有操作。
参数选择时把N作为源因子,‘A’ ‘B’ ‘C’作为表示操作的行为因子。则其函数表达式为:
void sethan1(int count,char source,char destination,char medium) { if(count==1) cout<<"Move top disk from pole "<<source<<" to pole "<<destination<<endl; else { sethan1(count-1,source,medium,destination); sethan1(1,source,destination,medium); sethan1(count-1,medium,destination,source); } } 或 void sethan2(int count,char source,char destination,char medium) { if(count>0) { sethan2(count-1,source,medium,destination); cout<<"Move top disk from pole "<<source<<" to pole "<<destination<<endl; sethan2(count-1,medium,destination,source); } }查找数组最大项:
在数组Array中查找最大项,分解数组为两个部分,分别找出最大项然后进行比较,取最大值。当分解的数组只有一项时,则其最大值即为该唯一项,由此可确定基例。
将数组的两个部分分别视作已完成的整体(即分别取得两个部分的最大值),然后进行比较,取最大值返回。

参数选择时,把arr作为源因子,first last作为控制因子。则其函数表达式为:

int searchMax1(int arr[],int first,int last) { if(first>=last) return arr[first]; else { int mid=(first+last)/2; return max(searchMax1(arr,first,mid),searchMax1(arr,mid+1,last)); } } int searchMax2(int arr[],int first,int last) { if(first>=last) return arr[first]; else { int mid=(first +last)/2; if(searchMax2(arr,first,mid)>=searchMax2(arr,mid+1,last)) return searchMax2(arr,first,mid); else return searchMax2(arr,mid+1,last); } }
折半查找法
在已排序的数组array中查找指定值,分解数组为两个部分,判断指定值位于哪个部分,然后再将指定值所在的部分数组进行分解。
当分解的数组中只含有一项时,达到基例或者只含有一项时并且与指定值不相等时为基例(因为这是一个返回值函数,当存在指定值时已经返回,不存在指定值可作为基例)。
将数组的两个部分分别视作已完成的整体(具有返回值,或找到或找不到),返回由判断可知的那部分数组。

参数选择,传递一个源因子,first last 作为控制因子,则其函数表达式为:

int binarySearch(int arr[],int first,int last,int key) { if(first>last) return -1; else { int mid=(first+last)/2; if(arr[mid]<key) return binarySearch(arr,mid+1,last,key); else if(arr[mid]==key) return mid; else return binarySearch(arr,first,mid-1,key); } }

查找第k最小项:

这个我理解的不到位就不多说了。函数表达式为:

//using the first item as the pivot and sort the array arr which is satisfy //for first part region items smaller than pivot and second part region //items equal or bigger than pivot. //look for the pivot P,and return it's position in arr; //the return value is absolute int findP1(int arr[],int first,int last) { int lastS1=first;//lastS1 stands for S1 region's last position. int firstUn=first+1;//fisrt stands for unknown region's first position. while(firstUn<=last&&first<=last) { if(arr[first]<=arr[firstUn]) firstUn++; else { int temp=arr[lastS1+1]; arr[lastS1+1]=arr[firstUn]; arr[firstUn]=temp; lastS1++; firstUn++; } } return lastS1; } //the return value is relative //and reset pivot in "right "position . int findP2(int arr[],int first,int last) { int lastS1=first; int firstUn=first+1; int temp; while(firstUn<=last) { if(arr[first]<=arr[firstUn]) firstUn++; else { temp=arr[lastS1+1]; arr[lastS1+1]=arr[firstUn]; arr[firstUn]=temp; lastS1++; firstUn++; } } temp=arr[first]; arr[first]=arr[lastS1]; arr[lastS1]=temp; return lastS1-first; } //the return value is absolute, //and reset the pivot in "right "position. int findP3(int arr[],int first,int last) { int lastS1=first; int firstUn=first+1; int temp; while(firstUn<=last) { if(arr[first]<=arr[firstUn]) firstUn++; else { temp=arr[lastS1+1]; arr[lastS1+1]=arr[firstUn]; arr[firstUn]=temp; lastS1++; firstUn++; } } temp=arr[first]; arr[first]=arr[lastS1]; arr[lastS1]=temp; return lastS1; } int kSmall1(int k,int arr[],int first,int last) { int p=findP1(arr,first,last); if(k<p-first+1) return kSmall1(k,arr,first+1,p); else if(k==p-first+1) return arr[first]; else return kSmall1(k-p+first-1,arr,p+1,last); } int kSmall2(int k,int arr[],int first,int last) { int p=findP2(arr,first,last); if(k<p+1) return kSmall2(k,arr,first,p-1+first); else if(k==p+1) return arr[p+first]; else return kSmall2(k-p-1,arr,first+p+1,last); } int kSmall3(int k,int arr[],int first,int last) { int p=findP1(arr,first,last); if(k<p+1) return kSmall3(k,arr,first+1,p); else if(k==p+1) return arr[first]; else return kSmall3(k,arr,p+1,last); } int kSmall4(int k,int arr[],int first,int last) { int p=findP3(arr,first,last); if(k<p+1) return kSmall4(k,arr,first,p-1); else if(k==p+1) return arr[p]; else return kSmall4(k,arr,p+1,last); }

reference

《Data Abstraction and Problem Solving wiht c++ 》(Fourth Edition)


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值