尾递归不是伪递归啊喂!

  • 概念:
    • 如果一个函数中所有递归形式的调用都出现在函数的末尾,我们称这个递归函数是尾递归的。当递归调用是整个函数体中最后执行的语句且它的返回值不属于表达式的一部分时,这个递归调用就是尾递归。尾递归函数的特点是在回归过程中不用做任何操作,这个特性很重要,因为大多数现代的编译器会利用这种特点自动生成优化的代码。

  • 尾递归优势:
    • 与普通递归相比,由于尾递归的调用处于方法的最后,因此方法之前所积累下的各种状态对于递归调用结果已经没有任何意义,因此完全可以把本次方法中留在堆栈中的数据完全清除,把空间让给最后的递归调用。这样的优化便使得递归不会在调用堆栈上产生堆积,意味着即时是“无限”递归也不会让堆栈溢出。这便是尾递归的优势。

  • 举个例子:
    以阶乘为例:
    正常递归:
    func formalRecursion(n int) int {
        if n<=0 {
            return 0
        }
        if n==1 {
            return 1
        }
        return n*formalRecursion(n-1)
    }
    
    尾递归:
    var a int = 1
    func tailRecursion(n int,a int) int {
        if n<=0 {
            return 0
        }
        if n==1 {
            return a
        }
        return tailRecursion(n-1,n* a)
    }  
    ```
只可惜。。。golang的编译器对尾递归并没有优化。。。
那么golang这样写尾递归:
// 这个是有进行优化的。因为recursionChannel函数执行完毕后,直接就销毁了,没有接着保留堆栈
func recursionChannel(n int, a int, result chan int) {
    a = n*a
    if n <= 0 {
        result <- 0
        return 
    }
    if n == 1 {
        result <- a
        return
    }
    go recursionChannel(n-1, a, result)  // 无需等待返回
}

发布了32 篇原创文章 · 获赞 0 · 访问量 664

猜你喜欢

转载自blog.csdn.net/nku_ztq/article/details/103291183