数据结构之递归(思想加例子)

数据结构之递归

什么是递归?

递归的概念: 多点几次第一行的文字,或许可以从中悟出点什么,所谓递归调用就是某一方法调用自身,这种自我调用的方法可以是直接的也可以是间接的。

递归的价值: 递归的价值在于许多问题都可以简洁而准确地描述位d递归形式。

线性递归: 每一次递归调用自身至多调用一次,这种问题可以总可以分解成两个独立的子问题:其一对于单独的元素,可以直接求解,比如A[n - 1];另一个则是剩余部分,最重要的是这个剩余部分的求解方法和原问题一样,就是子问题。然后把这两个问题合并就是问题的解。

//数组求和递归版
int sum(int A[], int  n){
	if(1 > n)            //平凡情况,递归基,递归出口
		return 0;
	else                 //一般情况
		return sum(A, n - 1) + A[n - 1];
}

减而治之: 线性递归的模式往往对应于所谓减而治之的算法策略:递归每深入一层,待求解问题的规模都缩减一个常数,直至最终蜕变为平凡的小问题。

多递归基:

//数组倒置
void reverse(int* A, int lo, int hi){
	if(lo < hi){
		swap(A[lo], A[hi]);
		reverse(A, lo + 1, hi - 1);
	}//else隐藏了两种递归基,其中数组元素偶数个对应的是lo > hi;
	  //奇数个数是lo = hi;
} 

多向递归: 递归调用的分支可能有多个。但任然是线性递归。
快速幂算法:

__int64 power(int a, int n){
	if(0 == n)
		return 1;
	__int64 temp = power(a , n / 2);
	if(n % 2 == 1)
		return temp * temp * a;
	else
		return temp * temp;
}

二分递归:
分而治之:面对比较大的规模的问题,如果我们没有头绪,不妨试试用这种分而治之的策略来思考问题,与减而治之的策略有类似之处的是分而治之也要把问题进行分解,但是这里拆分长两个子问题。既然有二分递归,那么也就有多路递归,这取决于拆分的子问题的个数,但是无论是分解成两个或是更大常数个子问题,对算法的总体渐进复杂度没有实质影响。

//数组求和二分递归版
int sum(int A[], int lo, int hi){
	if(lo == hi)
		return A[lo];
	else{
		int mi = (lo + hi) >> 1;
		return sum(A, lo, mi) + sum(A, mi + 1, hi);
	}
}
//斐波那契数二分递归
__int 64 fib(int n){
	if(n == 1 || n == 2)
		return 1;
	else
		return fib(n - 1) + fib(n - 2);
}
//斐波那契二分递归优化版本线性递归
__int64 fib(int n, __int64& prev){
    if(0 == n){
        prev = 1;
        return 0;
    }
    else{
        __int64 prePrev;
        prev  = fib(n - 1, prePrev);
        return prePrev + prev;
    }
}//不是很好理解,要仔细琢磨

递归的消除: 前面介绍的这么多递归,最后突然来一个递归的消除,看起来很矛盾,其实事实就是如此,递归如此的简洁也是需要代价的,而这个代价的来源就是递归调用需要花费大量额外时间以创建、维护和销毁各递归实例,同时递归需要花费大量的空间,如果递归的深度太深会造成栈溢出,而递归的消除就是用来替换,简单的尾递归可以用循环消除。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值