递归的应用
递归介绍
递归,作为计算机科学中的一个重要工具,其算法思想相对简单,能解决许多较为复杂的编程问题。数据结构中,递归算法的用途相当广泛,树、二叉树、图、查找、排序等算法中也常用到递归思想。本篇将对递归进行简单总结,以几个例子简单的介绍一下递归算法[1]。
递归能解决什么问题?
对于定义或数据结构是递归的时候,比如树,链表,一些递归数列(如Fibonacci数列等等) |
---|
问题的求解是递归的时候,比如耳熟能详的Hanoi问题等等 |
对于递归我们需要注意什么问题?
*要使用递归算法,首先需要解决的问题是能够转换为小问题的,即大问题->小问题,同时这些小问题和大问题的求解方法完全相同。
递归算法在CPU中是如何实现的?
在CUP中,函数的调用是使用函数调用栈(栈帧)进行操作,对于递归问题,每次调用函数时,系统会
将函数的函数实参,局部变量值和返回地址保存在帧中压入调用栈从而实现函数的调用
递归问题实例
在我们解决明显是递归问题的时候,我们往往都要先确定递归出口是什么?递归体是什么?因此对于一般的问题,我们想要递归解决,我们的递归出口往往是问题中的一些临界约束,而递归体则是问题中可能出现的情况的总和!
问题一:恢复IP地址问题
问题描述:给定一个仅包含数字的字符串,恢复它的所有可能的有效IP地址。
问题实例:
输入:“25525511135”
输出:“255.255.11.135” 和 “255.255.111.35”
递归算法思想:
对于一个合法的IP地址,它是由4个子串构成,每个子串需要大于0且小于255,除此之外,每个子串只能包含1~3个字符。
我们想要解决这个问题我们首先对大问题进行分解
大问题:将这11个字符恢复成为IP地址(需要对每个子串后面加’.’) |
小问题:将每1~3个字符组成一个子串恢复为IP地址格式 |
递归出口:已经对这11个字符全部处理问题,即start>=n,且得出了四个子串(start初始为0,用于扫描整个字符串,字符串长度为n) |
递归体:当字符串没有扫描完毕时 |
代码示例:
#include <stdio.h>
#include <string.h>
#define MaxSize 100
typedef struct
{
char data[MaxSize]; // 用于存放整个IP地址
int length; // IP地址字符串长度,方便输出
}IP;
void addch(IP &ip, char ch) // 往ip中加入字符ch
{
ip.data[ip.length++] = ch;
}
IP adddot(IP ip) // 往ip中加入每个子串后的'.',返回一个ip
{
addch(ip,'.');
return ip;
}
void getip(char s[], int n, int start, int no, IP ip)
// n为字符串s长度,start是初始扫描位置,no是扫描的第几个子串
{
if(start == n && no == 4) // 递归出口:已经对这11个字符全部处理问题,因为no是从0开始,所以no==4时已经有四个子串了
{
for(int i=0;i<ip.length-1;i++) // i<ip.length-1是为了不输出最后的'.'
printf("%c",ip.data[i]);