• Python 递归、排序和搜索


    一、递归

    1 生活中的递归

    1)我们使用的词典,本身就是递归,为了解释一个词,需要使用更多的词。当你查一个词,发现这个词的解释中某个词仍然不懂,于是你开始查这第二个词,可惜,第二个词里仍然有不懂的词,于是查第三个词,这样查下去,直到有一个词的解释是你完全能看懂的,那么递归走到了尽头,然后你开始后退,逐个明白之前查过的每一个词,最终,你明白了最开始那个词的意思。

    2)多年前我五岁的儿子问我「不是每条船都有救生艇的吧?」「怎么会呢?」「也许救生艇上会有一艘更小的救生艇,但是那艘小艇上可能就没有更小的救生艇了。」

    3)一个洋葱是一个带着一层洋葱皮的洋葱。

    2 递归的原则

    • 递归算法必须有停止条件
    • 递归算法必须改变其状态并向停止条件靠近
    • 递归算法必须递归地调用自己

    3 应用场景

    3.1 数字累加和

    1. # 3 + 2 + 1
    2. def sum_numbers(num):
    3. # 1.如果是1,直接返回1 -- 出口
    4. if num == 1:
    5. return 1
    6. # 2.如果不是1,重复执行累加并返回结果
    7. return num + sum_numbers(num-1)
    8. # 输出结果为6
    9. print(sum_numbers(3))

    分析:

     

    3.2 n以内的数字阶乘

    1. # 数字阶乘
    2. def Fact(n):
    3. if n == 1:
    4. return 1
    5. return n * Fact(n-1)

    3.3 斐波那切数列

    1. # 斐波那契数列
    2. def Fibo(n):
    3. # 出口
    4. if n == 1 or n == 2:
    5. return 1
    6. else:
    7. return Fibo(n - 1) + Fibo(n - 2)

    分析:

            这样一个数列:1、1、2、3、5、8、13、21、34、……在数学上,斐波那契数列以如下被以递推的方法定义:F(1)=1, F(n)=F(n - 1)+F(n - 2)(n ≥ 2,n ∈ N*)

    二、排序

    1 快速排序

    1.1 规则

    • 从数列中挑出一个基准值。
    • 将所有比基准值小的摆放在基准前面,所有比基准值大的摆在基准的后面(相同的数可以到任一边);在这个分区退出之后,该基准就处于数列的中间位置。
    • 递归地把"基准值前面的子数列""基准值后面的子数列"进行排序。 

    1.2 步骤解析

     

    1.3 代码实现

    1. # 快速排序
    2. def partition(li,left,right):
    3. tmp = li[left]
    4. while left < right:
    5. while left < right and li[right] >= tmp: #从右边找比tmp小的数
    6. right -= 1 #继续从右往左查找
    7. li[left] = li[right] #把右边的值写到左边空位上
    8. while left < right and li[left] <= tmp:
    9. left += 1
    10. li[right] = li[left] #把左边的值写到右边空位上
    11. li[left] = tmp #把tmp归位
    12. return left
    13. def quick_sort(li,left,right):
    14. if left < right : #至少两个元素
    15. mid = partition(li, left, right)
    16. quick_sort(li, left, mid-1)
    17. quick_sort(li, mid+1, right)
    18. li = [5, 7, 4, 6, 3, 1, 2, 9, 8]
    19. quick_sort(li, 0, len(li)-1)
    20. print(li)

    1.4 各项指标

            1)快速排序是一个不稳定的排序算法

            2)时间复杂度

                    平均:O(nlogn)

                    最差:O(n2),退化为冒泡排序

    2 归并排序

    2.1 概念

            归并排序用的是分治法,把一个大问题化解为k个中问题,每个中问题再化解为k个小问题,直至问题化为最小可解的问题。对这些问题求解,再不断地合并结果,直至合并完毕。

    2.2 步骤解析

     

    2.3 代码实现

    1. # 归并排序
    2. # 1.将整个数组对半分开,直到只剩一个元素
    3. # 2.从一个元素开始往回进行对比合并,将合并的内容暂且放在一个空列表中
    4. # 定义合并merge函数
    5. def merge(L,R):
    6. # 将两个排过序的两个列表进行合并并排序
    7. # 分别用于限定L、R的数据减少情况
    8. i, j = 0,0
    9. # 用于存放L与R的合并内容
    10. res = []
    11. while i < len(L) and j < len(R):
    12. # 如果左边的数大于右边的数,就将左边的数先添加到res中,再继续比较(合并的R、L已经排过序)
    13. # 如果如果右边的数大于左边的数,就将右边的数先添加到res中,再继续比较(合并的R、L已经排过序)
    14. if L[i] <= R[j]:
    15. res.append(L[i])
    16. i += 1
    17. else:
    18. res.append(R[j])
    19. j += 1
    20. # 因为当 i == len(L) 或者 j == len(R)时,跳出while循环,且每次循环只处理一个列表里的内容,所以其中有一个列表内容会先全部加入res中,另一个列表还剩内容未加进res中。
    21. # 对未处理完的列表,直接加入res中
    22. res += R[j:] if i == len(L) else L[i:]
    23. return res
    24. # 定义排序merge_sort函数
    25. def merge_sort(List):
    26. length = len(List)
    27. if length <= 1:
    28. return List
    29. else:
    30. mid = length//2
    31. left = merge_sort(List[:mid])
    32. right = merge_sort(List[mid:])
    33. return merge(left,right)
    34. if __name__ == '__main__':
    35. List = [9,8,7,5,3,6,11,2,4,1,12]
    36. print(merge_sort(List))

    2.4 各项指标

            不管待排序列表的初始状态如何,都不影响排序的时间复杂度。归并排序一直对待排序列表进行拆分,需要进行logn次拆分,在每一次递归合并中,需要进行n次比较和添加。时间复杂度为 T(n)=nlogn ,再乘每次操作的步骤数(常数,不影响大O记法),所以归并排序的时间复杂度为 O(nlogn) 。

    3 冒泡排序

    3.1 概念

            冒泡排序(Bubble Sort)也是一种简单直观的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。

    3.2 步骤解析

    第一次循环:

    第二次循环: 

     

    第三次循环: 

     

    第四次循环: 

     

     

     3.3 代码实现

    1. # 冒泡排序
    2. def func_sort(n):
    3. for i in range(n-1): # 控制排序次数
    4. for j in range(n-1-i): # 控制比较次数
    5. if L[j]>L[j+1]:
    6. print('{}比{}大,交换前{}'.format(L[j], L[j + 1], L))
    7. L[j], L[j + 1] = L[j + 1],L[j]
    8. print('交换后:{}'.format(L))
    9. else:
    10. print("我不用交换{}".format(L))
    11. print('排序后的列表为:{}'.format(L))
    12. func_sort(len(L))

    3.4 各项指标

            时间复杂度是O(n^2),是一种稳定的算法

    4 选择排序

    4.1 概念

            选择排序(Selection sort)是一种简单直观的排序算法。它的工作原理是每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,所以称为:选择排序

    4.2 步骤解析

     

    4.3 代码实现

    4.4 各项指标

    5 插入排序

    5.1 概念

            插入排序(Insertion-Sort)的算法描述是一种简单直观的排序算法。它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。

    5.2 步骤解析

    5.3 代码实现

    1. # 插入排序
    2. def insertion_sort(sort_list):
    3. # 注意是从第二个位置开始向前插入元素
    4. for i in range(1, len(sort_list)):
    5. # 从第i个元素开始向前比较,如果小于前一个元素,交换位置
    6. for j in range(i, 0, -1):
    7. if sort_list[j] < sort_list[j - 1]:
    8. sort_list[j - 1], sort_list[j] = sort_list[j], sort_list[j - 1]
    9. test_llst = [5, 4, 6, 3, 1, 2]
    10. print(test_llst)
    11. insertion_sort(test_llst)
    12. print(test_llst)

    5.4 各项指标

            最优时间复杂度:O(n)
            最坏时间复杂度:O(n2)

    三、搜索

    1 二分搜索

    1.1 概念

            二分搜索是一种在有序数组中查找某一特定元素的搜索算法。搜索过程从数组的中间元素开始,如果中间元素正好是要查找的元素,则搜索过程结束;如果某一特定元素大于或者小于中间元素,则在数组大于或小于中间元素的那一半中查找,而且跟开始一样从中间元素开始比较。如果在某一步骤数组为空,则代表找不到。这种搜索算法每一次比较都使搜索范围缩小一半。

    1.2 步骤解析

     1.3 代码实现

    1. # 二分查找
    2. lss = [12, 27, 29, 32, 35, 54, 60, 70, 71, 91]
    3. def b_search(ls, target):
    4. def bin_search(ls, target, l, r):
    5. if l > r:
    6. return -1
    7. mid = int(l + (r - l) / 2)
    8. if ls[mid] == target:
    9. return mid
    10. elif ls[mid] < target:
    11. return bin_search(ls, target, mid + 1, r)
    12. else:
    13. return bin_search(ls, target, l, mid - 1)
    14. return bin_search(ls, target, 0, len(ls)-1)
    15. print(b_search(lss, 70))
    16. print(b_search(lss, 222))

    1.4 各项指标

            二分查找的时间复杂度为O(log2n)

    四、参考

    1.Python实现快速排序_想成大神的大艳的博客-CSDN博客_快速排序python

    2.归并排序(Python代码)_莱维贝贝、的博客-CSDN博客_python 归并排序 

    3.Python二分搜索算法___Miracle__的博客-CSDN博客_python二分查找算法 

    4.Python实现冒泡排序详解_芃小黄的博客-CSDN博客_python冒泡排序流程图 

  • 相关阅读:
    图像对比算法有哪些,图像对比算法是什么
    什么是域名?如何注册域名?
    Nginx 面试题
    opencv(11):训练自己的opencv级联分类器
    【面试题】—— 笔试题(4题)
    LVS-NAT模式实验案例
    英特尔会是下一个诺基亚吗?
    antd pro form 数组套数组 form数组动态赋值 shouldUpdate 使用
    根据您的数据量定制的ChatGPT,改变客户服务的方式
    [Servlet 1] JSP基础知识
  • 原文地址:https://blog.csdn.net/qq_21370419/article/details/126366294