递归c++

特点

  • 找出相似性
  • 出口设计
  • 循环可以转成递归
  • 递归效率较差

递归求字符串长度

  • 首先,求整个串的长度,stringLen§
  • 再求去掉第一个字符的串长度,stringLen(p+1)
  • 依次展开,直至遇到出口*p==0
    在这里插入图片描述

代码

int stringLen(const char* p){
	if(p==0)
		return 0;
	if(*p==0)
		return 0;
	return 1+stringLen(p+1);
}

字符串大小比较-递归

在这里插入图片描述

  • 寻找规律,先从第一个字符开始比较,如果相同就比较第二个
  • 相似性,比较字符,如果相等,就把问题抛给下一个,谁大谁小由下一个字符决定。
  • 出口,先遇到结束标志’\0’,说明串短,属于小的。
  • 如果都到了结束标志’\0’,说明相等

代码

#include<iostream>
using namespace std;
int strcmp(const char* a,const char* b){
	if(*a=='\0' && *b=='\0')
		return 0;
	if(*a=='\0') 
		return -1;
	if(*a=='\0') 
		return 1;
	if(*a != *b)
		return *a - *b;
	return strcmp(a+1,b+1);	
}
int main(){
	cout << strcmp("abed","abdc")<<endl;
	return 0;
} 

冒泡排序-递归

在这里插入图片描述

  • 冒泡排序过程(从小到大),从第一个元素开始,相邻元素相互比较,如果比后面的数大,则交换。再与后面的元素比较,一轮下来之后,最后一个元素最大。如上图,9比7大,交换。9与3比较,大则交换。9比6大,又交换。9比11小,位置不变。
  • 数组的元素个数为n,则第一个循环需比较n-1次,下个循环比较n-2次,最后剩1个元素,则不用比较,是出口。
  • 相似性构造,sort(a,n)表示a数组的n个元素进行冒泡排序,第一回把最大的排到最右边,剩下的n-1个元素进行冒泡排序便是sort(a,n-1)。把加黑的功能由另一个递归函数实现。
  • 第一回把最大的排到最右边,n个元素相邻的相互比较,需要比较n-1次,构造一个比较交换函数sort_branch(a,n-1),它的含义为a数组的n个元素比较n-1次,大的交换到后面。
  • 递归实现sort_branch(a,n-1),第一个元素与第二个比较,大则交换,否则不变。比较一次后,把问题交给下一个,下个从第二个数组元素开始,数组的个数少一个,即sort_branch(a+1,n-2)。相邻比较的特点是最少有2个元素,比较1次。如果数组只有1个元素,那就比较0次,函数的出口。

代码

#include<iostream>
using namespace std;
void swap(int* a,int* b){
	int c=*a;
	*a=*b;
	*b=c;
}
void sort_branch(int *a,int n){
	if(n==0)
		return;
	if(a[0]>a[1])
		swap(a[0],a[1]);
	sort_branch(a+1,n-1);
}
void sort(int *a,int n){
	if(n==1)
		return;
	sort_branch(a,n-1);
	sort(a,n-1);
}
void show(int* a,int n){
	if(n==0)
		return;
	cout<<*a<<" ";
	show(a+1,n-1);
}
int main(){
	int a[]={9,7,12,5,65,99,15};
	int n=sizeof(a)/sizeof(int);
	sort(a,n);
	show(a,n);
	return 0;
} 

爬台阶-间接调自己

  • a、b、c都是函数,a调b,b调c,c调a

题目

  • 如果我每一步只能迈上1个或2个台阶。先迈左脚,然后左右交替,最后一步是迈右脚,也就是说一共要走偶数步。那么,上完n级台阶,有多少种不同的上法呢

方法一

在这里插入图片描述

  • 总步数是偶数步,做2个递归函数,n阶台阶偶数步爬完的种数为climb_stairs_even(int n),n阶台阶奇数步爬完的种数为climb_stairs_odd(int n)
  • 总步数是偶数步,故函数从偶数开始,然后是奇数步。
  • 出口就是1、2个台阶分别对应的奇偶数步
#include<iostream>
using namespace std;
//爬奇数个台阶 
long long climb_stairs_even(int );
long long climb_stairs_odd(int n){
	if(n==1) return 1;
	if(n==2) return 1;
	return climb_stairs_even(n-1)+climb_stairs_even(n-2); 
}
//爬偶数个台阶 
long long climb_stairs_even(int n){
	if(n==1) return 0;
	if(n==2) return 1;
	return  climb_stairs_odd(n-1)+climb_stairs_odd(n-2);
}
int main(){
	cout<<climb_stairs_even(5)<<endl;
	return 0;
}

方法二

  • 先左后右,必须是左脚开始,右脚结束
  • 定义2个函数,左脚上完n个台阶的总方法数为l(int n),右脚上完n个台阶的总方法数为r(int n)
  • 出口就是左右脚上完1、2个台阶的方法数。
#include<iostream>
using namespace std;
long long r(int);
long long l(int n){
	if(n==1) return 0;
	if(n==2) return 1;
	return r(n-1)+r(n-2);
}
long long r(int n){
	if(n==1) return 1;
	if(n==2) return 1;
	return l(n-1)+l(n-2);
}
int main(){
	cout<<l(5)<<endl;
	cout<<l(40)<<endl;
	return 0;
}

分零钱

题目

  • 有50美分、25美分、10美分、5美分和1美分的硬币,将1美元(100美分)换成零钱,一共有多少种不同方式?
  • 找相似性,从总的不同方式开始递归。
  • 总的不同方式包括:不含50美分的情况,至少含一个50美分的情况。
  • 定义f(m,n)函数,表示钱值m,由n种硬币表示时的不同方式数。
  • f(100,5),即100美分,由50美分、25美分、10美分、5美分和1美分一共5种硬币表示的方法数。
  • f(100,4),即100美分,由25美分、10美分、5美分和1美分一共4种硬币表示的方法数。
  • 出口,当只用1美分硬币表示时的方法数为1,钱数m为负数时的方法数为0。m=0时,即f(0,n)它的意思是钱数为coins[n]时至少含一个coins[n]的方法数,显然此时只有1种方式。

代码

#include<iostream>
using namespace std;
const int coins[]={0,1,5,10,25,50};
int f(int m,int n)
{
	if(n==1) return 1;
	if(m<0) return 0;
	if(m==0) return 1;
	return f(m,n-1) + f(m-coins[n],n);
}
int main()
{
	cout<<f(100,5);
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值