• 算法前戏 递归 二分查找 列表查找


    一、递归

    概念:

      函数直接或者间接的调用自身算法的过程,则该函数称为递归函数。在计算机编写程序中,递归算法对解决一大类问题是十分有效的。

    特点:

      ①递归就是在过程或者函数里调用自身

      ②在使用递归策略时,必须有一个明显的结束条件,称为递归出口。问题规模相比上次递归有所减少,

      ③递归算法解题通常显得很简洁,但递归算法解题的效率较低。所以一般不倡导使用递归算法设计程序。

      ④在递归调用的过程当中系统的每一层的返回点、局部变量等开辟了栈来存储。递归函数次数过多容易造成栈溢出等。

      所以一般不倡导用递归算法设计程序。

    要求:

    递归算法所体现的"重复"一般有三个条件:

      ①每次在调用规模上都有所缩小(通常是减半)。

      ②相邻两次重复之间有紧密的联系,前一次要为后一次做准备(通常前一次的输出就作为后一次的输入)。

      ③在问题的规模极小时必须用直接解答而不再进行递归调用,因而每次递归调用都是有条件的(以规模未达到直接解答的大小为条件),

    无条件的递归调用将会成为死循环而不能正常结束。

    分析以下函数的执行过程:

    def func3(x):    
        if x>0:        
            print(x)        
            func3(x-1)
    
    func3(5)
    
    def func4(x):    
        if x>0:       
             func4(x-1)       
             print(x)
    
    func4(5)
    

      根据Python执行的过程,及函数调用去分析执行结果!

     关于斐波拉契数列

      斐波拉契数列指的是这样一个数列:0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233,377,610,987,1597,2584,4181,6765,10946,17711,28657,46368。

    特别注意:第0项是0,第1项是第一个1。这个数列从第2项开始,每一项都等于前两项之和。

    def fibo(n):
        before = 0
        after = 1
        if n == 0 or n == 1:
            return n
    
        if n <= 3:
            return 1
        return fibo(n-1)+fibo(n-2)
    
    print(fibo(3))
    斐波那契数列

    二分查找

      从有序列表的候选区data[0:n]开始,通过对待查找的值与候选区中间值的比较,可以使候选区减少一半。

    特点:

      二分查找算法就是不断将数组进行对半分割,每次拿中间元素和要找的元素进行比较。小就向右找,大就向左找!

    要求:  

      在一段数字内,找到中间值,判断要找的值和中间值大小的比较。
        如果中间值大一些,则在中间值的左侧区域继续按照上述方式查找。
        如果中间值小一些,则在中间值的右侧区域继续按照上述方式查找。
      直到找到我们希望的数字。

    def search_data(data,data_find):
        # 中间值的索引号的定义:数组长度/2
        mid = int(len(data)/2)
        # 判断从1开始的数字数组内查找
        if data[mid] >= 1:
            # 如果我们要找的值(data_find)比中间值(data[mid])小
            if data[mid] > data_find:
                print("你要找的数字比中间值[%s]小..." % data[mid])
                # 在中间值(data[mid])的左侧继续查找,在此函数中继续循环
                search_data(data[:mid],data_find)
            # 如果我们要找的值(data_find)比中间值(data[mid])大
            elif data[mid] < data_find:
                print("你要找的数字比中间值[%s]大..." % data[mid])
                # 在中间值(data[mid])的右侧继续查找,在此函数中继续循环
                search_data(data[mid:],data_find)
            else:
                # 如果我们要找的值(data_find)既不比中间值(data[mid])大,也不比中间值(data[mid])小,则就是它
                print("这就是你要找的[%s]!" % data[mid])
        else:
            print("不好意思,没有找到你要的值...")
    
    if __name__ == '__main__':
        # 创建一个1到6000万的连续数字数组
        data = list(range(60000000))
        # 调用函数找到95938的值
        search_data(data,95938)
    相关代码举例

    列表查找

    列表查找:从列表中查找指定元素
      输入:列表、待查找元素
      输出:元素下标或未查找到元素

    一般是有两种方法:

    1、顺序查找

      从列表第一个元素开始,顺序进行搜索,直到找到为止。

    def linear_search(data_set,value):
        for i in data_set:
            if data_set[i] == value:
                return i

    2、二分查找

      从有序列表的候选区data[0:n]开始,通过对待查找的值与候选区中间值的比较,可以使候选区减少一半。

    def bin_search(data_set,value):
        low = 0
        high = len(data_set)-1
        while low <= high:
            mid = (low+high)//2
            if data_set[mid] == value:
                return mid
            elif data_set[mid] > value:
                high = mid - 1
            else:
                low = mid + 1
    
    def bin_search(data_set,value,low,high):
        if low <= high:
            mid = (low+high)//2
            if data_set[mid] == value:
                return mid
            elif data_set[mid] >value:
                return bin_search(data_set,value,low,high)
            else:
                return bin_search(data_set, value, low, high)
        else:
            return
    二分查找递归版

    练习题:

    现有一个学员信息列表(按id增序排列),格式为:
    	[
    		{"id":1001, "name":"张三", "age":20},
    		{"id":1002, "name":"李四", "age":25},
    		{"id":1004, "name":"王五", "age":23},
    		{"id":1007, "name":"赵六", "age":33}
    	]
    
    修改二分查找代码,输入学生id,输出该学生在列表中的下标,并输出完整学生信息。
    
    l = [
        {"id":1001, "name":"张三", "age":20},
        {"id":1002, "name":"李四", "age":25},
        {"id":1004, "name":"王五", "age":23},
        {"id":1007, "name":"赵六", "age":33}
    ]
    
    def bin_search(data_set,value):
        """
        二分查找
        :param data_set: 列表
        :param value: 要查的值
        :return:
        """
        low = 0
        high = len(data_set)-1
        while low <= high:
            mid = (low+high)//2
            if data_set[mid]['id'] == value:
                return (mid,data_set[mid])
            elif data_set[mid]['id'] > value:
                high = mid - 1
            else:
                low = mid + 1
        else:
            return (0,None)
    
    flog = True
    while flog:
        sid = input("请输入学号(退出:Q):").strip()
        if sid.isdigit():
            if sid.upper() == "Q":
                flog = False
            else:
                sid = int(sid)
                mid,infos = bin_search(l,sid)
                if not infos:
                    print("查无此人!!!")
                else:
                    s = "学生学号:{id},姓名:{name},年龄:{age}".format(**infos)
                    print("该学生所在信息索引坐标:%s"%mid)
                    print("该学生的所有信息:%s"%s)
    
  • 相关阅读:
    js事件委托篇(附js一般写法和js、jq事件委托写法)
    markdown工作随笔总结
    论实际开发中按钮显示和隐藏自身或其他元素
    彻底理解行内元素和块级元素,不必硬背
    redis搭建主从配置
    [Python图像处理]三.获取图像属性及通道处理
    [Python图像处理]二 OpenCV借助Numpy库读取和修改像素
    [Python图像处理]一.图像处理基础知识及OpenCV入门函数
    opencv2图像处理--灰度变换
    提取新闻网站信息
  • 原文地址:https://www.cnblogs.com/zh605929205/p/7467231.html
Copyright © 2020-2023  润新知