本文原创文章,转载注明出处,博客地址 https://segmentfault.com/u/to... 第一时间看后续精彩文章。觉得好的话,顺手分享到朋友圈吧,感谢支持。

栈的应用-递归

递归函数定义

我们把一个直接调用自己或通过一系列的调用语句间接地调用自己的函数,称做递归函数

迭代和递归的区别

迭代代码,实现斐波那契额数列

//版本1:迭代版本
func Fbi1(i int) int {

    switch i {
    case 0:
        return 0
    case 1:
        return 1
    default:
        arr := make([]int, i+1, i+1)
        arr[0] = 0
        arr[1] = 1
        for j := 2; j <= i; j++ {
            arr[j] = arr[j-1] + arr[j-2]
        }
        return arr[i]
    }
}

递归代码

//版本2:递归版本
func Fbi2(i int) int {
    switch i {
    case 0:
        return 0
    case 1:
        return 1
    default:
        //递归调用
        return Fbi2(i-1) + Fbi2(i-2)
    }
}
  1. 迭代使用的是循环结构,递归使用的是选择结构
  2. 递归使程序的结构更清晰、更简洁、更容易理解,从而减少读懂代码的时间
  3. 但是大量的递归调用会建立函数的副本,会耗费大量的时间和内存,迭代则不需要反复调用函数和占用额外的内存

视不同情况选择不同的代码实现方式

编译器使用栈实现递归

递归过程分为前行和退回阶段,编译器使用栈实现递归;前行阶段,每一层递归,函数的局部变量、参数值以及返回地址都被压入栈,在退回阶段,位于栈顶的局部变量、参数值和返回地址被弹出,恢复了调用的状态

队列的定义

  1. 队列(Queue)是只允许在一端进行插入操作,而在另一端进行删除操作的线性表
  2. 先进先出(First In First Out),简称FIFO

循环队列

我们把队列的这种头尾相接的顺序存储结构称为循环队列

链队列

队列的链式存储结构,就是线性表的单链表,只能尾进头出

循环队列与链队列比较

  1. 循环队列是事先申请好空间,使用期间不释放;链队列,每次申请和释放阶段存在一些时间开销
  2. 循环队列必须有一个固定长度,有存储元素个数和空间浪费的问题;空间上,链队列更加灵活

总结:可以确定队列长度最大值的情况下,建议用循环队列,如果无法预估队列长度,则用链队列

总结回顾

  • 对于栈来说,如果两个相同数据类型的栈,则可以用数组的两端作栈底来让两个栈共享数据,可以最大化利用数组的空间
  • 循环队列使得队头和队尾可以在数组中循环变化,避免数组插入数据和删除时需要移动数据的时间损耗,使得本来插入和删除是O(n)的时间复杂度变成O(1)

tomorrowwu
444 声望27 粉丝

专注服务器开发,对区块链技术保持好奇心


引用和评论

0 条评论