【Day2】算法图解——学习笔记

三 递归

1. 递归概述

  • 递归函数调用自己,如果使用循环,程序的性能可能更高;如果使用递归,程序可能
    更容易理解。
  • 编写递归函数时,必须告诉它何时停止递归。正因为如此,每个递归函数都有两部分:基线
    条件(base case)和递归条件(recursive case)。递归条件指的是函数调用自己,而基线条件则
    指的是函数不再调用自己,从而避免形成无限循环。即:递归一定要有出口

2. 栈

  • 栈只有两种操作:压入(插入)和弹出(删除并读取)。

  • 栈的特点:后进先出

  • 递归实际上就是调用了栈

    递归调用栈的注意事项:

  • 使用栈虽然很方便,但是也要付出代价:存储详尽的信息可能占用大量的内存。每个函数调
    用都要占用一定的内存,如果栈很高,就意味着计算机存储了大量函数调用的信息。在这种情况
    下,你有两种选择。

    • 重新编写代码,转而使用循环。
    • 使用尾递归。这是一个高级递归主题,不在本书的讨论范围内。另外,并非所有的语言
      都支持尾递归。

3. 小结

  • 递归指的是调用自己的函数。
  • 每个递归函数都有两个条件:基线条件和递归条件。
  • 栈有两种操作:压入和弹出。
  • 所有函数调用都进入调用栈。
  • 调用栈可能很长,这将占用大量的内存。

四 快速排序

1. 分而治之策略

  1. 找出简单的基线条件;
  2. 确定如何缩小问题的规模,使其符合基线条件。

2. 快速排序

快速排序是一种常用的排序算法,比选择排序快得多。例如,C语言标准库中的函数qsort
实现的就是快速排序。快速排序也使用了D&C。

排序步骤:

  1. 选择基准值。
  2. 将数组分成两个子数组:小于基准值的元素和大于基准值的元素。
  3. 对这两个子数组进行快速排序(递归调用)。

时间复杂度

  • 一般情况下快速排序的时间复杂度为:O(n log n)

  • 快速查找的常量比合并查找小,因此如果它们的运行时间都为O(n log n),快速查找的速度将更快。实际上,快速查找的速度确实更快,因为相对于遇上最糟情况,它遇上平均情况的可能性要大得多。

  • 快排最坏情况和最好情况
    • 快速排序的性能高度依赖于你选择的基准值
    • 如果每次数组已经有序,而且每次都选取第一个数为基准值,那调用次数为n,栈长度为O(n),最佳情况下为O(log n ),每一层都将对所有数据进行排序,因此每层时间为O(n)
    • 如果是最佳情况,所需时间为O(n) * O(log n) = O(n log n)
    • 在最糟情况下,有O(n)层,因此该算法的运行时间为O(n) * O(n) = O(n^2)。
    • 最佳情况也是平均情况。只要你每次都随机地选择一个数组元素作为基准值,快速排序的平均运行时间就将为O(n log n)。快速排序是最快的排序算法之一,也是D&C典范。

3. 小结

  1. D&C将问题逐步分解。使用D&C处理列表时,基线条件很可能是空数组或只包含一个元
    素的数组。
  2. 实现快速排序时,请随机地选择用作基准值的元素。快速排序的平均运行时间为O(n log n)。
  3. 大O表示法中的常量有时候事关重大,这就是快速排序比合并排序快的原因所在。
  4. 比较简单查找和二分查找时,常量几乎无关紧要,因为列表很长时,O(log n)的速度比O(n)
    快得多。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值