递归 及二分法的使用

递归
递归指的是递归调用,简单地说就是一个函数在执行过程中又直接或是间接的调用该函数本身


递归调用本质上就是在循环执行代码,与普通循环不同的是,函数调用,会产生一系列内存开销,所以就会导致内存溢出,
而循环则没有这个问题,
如此一来,则表示所有递归能干的事情循环也能干.

在使用递归时要注意:
1.一定要在某个条件满足时结束循环调用
2.循环调用的次数不能超过系统的限制
3.每一次执行函数都应该使问题的规模减少,否则就是无用的循环
4.python中没有尾递归优化机制(使得递归调用时占用的开销更小)
递归时可能出现以下错误:
RecursionError: maximum recursion depth exceeded while calling a Python object
在调用函数时超出了最大递归深度
python为了防止递归太多导致内存溢出,所以给递归调用加上了深度(次数)限制,默认为1000

在使用递归完成遍历所有元素(不知道有几层)时,可以发现,递归使用起来,代码量更少,并且代码结构更加清晰
什么时候该使用递归:
你不知道到底要循环几次



"""
# def func():
# a = 100
# print("func run")
# func()
#
# func()
# while True:
# print("while func")

# name = "张三"

# def f1():
# print("f1 run")
# f2()
#
# def f2():
# print("f2 run")
# f1()
# f1()

# def f2():
# f3()
#
# def f1():
# f2()
#
# f1()
# import sys
#
# print(sys.getrecursionlimit())
# sys.setrecursionlimit(2000)
# print(sys.getrecursionlimit())

"""
person1 = person2+1000
person2 = person3+1000
person3 = person4+1000
person4 = 15000
person(n) = person(n+1)+1000
if n == 4 money=15000
"""

# def money(n):
# if n == 1:
# return 100
# else:
# return money(n-1) + 1
#
# res = money(4)
#
# print(res)


li = [1,[2,[3,[4]]]]
# 要求取出所有元素
#使用循环来完成
while True:
# 得明确知道此时列表中还有没有小列表
has_list = False
for i in li:
if type(i) == list:
li = i
has_list = True
else:
print(i)
if not has_list:
break


li = [1,[2,[3,[4]]]]
# 使用递归的方式来获取所有元素1
def show_list(li):
for i in li:
if type(i) == list:
show_list(i)
else:
print(i)
show_list(li)


"""
二分查找法
分半查找
折半查找
[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17]
原理:
现将整体分为两半
然后取出中间的元素,与你要查找的目标进行比对,如果你要找的比中间值大请走右边
如果你要找的比中间值小请走左边
1.先得到一个中间值,比较是不是你要找的如果是直接返回
2.如果不是 那就把列表拆为两半,进行比较
3.如果你要找的比中间值大找右边
如果你要找的比中间值小找左边
"""
# li = [1,2,3,4,5,6,7]
# def search(li,target):
# for i in li:
# if i == target:
# return True
# return False
# print(search(li,10))


li = [1,2,3,4,5,6,7,8,9,10,11,12,14,15,16,17,18,19,20]
def search(li,target):
print("start==============")
# 如果已经没有内容直接返回false
if not li:
return False
i = len(li) // 2
# 如果当前中间值就是要找的值 直接返回True
if li[i] == target:
return True
# 当要找目标不在整个列表中时,右侧的列表最后会拿着一个值死循环
if len(li) == 1:
return False
# 将列表切成两半
left = li[:i]
right = li[i:]
# 判断找左边还是右边
if target > li[i]:
return search(right,target)
else:
return search(left, target)

print(search(li,20))