python拓展3 算法与数据结构

知识内容:

1.递归复习

2.常用算法

3.常用数据结构

4.python cookbook算法与数据结构整理

参考资料:

http://python3-cookbook.readthedocs.io/zh_CN/latest/index.html

http://www.cnblogs.com/alex3714/articles/5474411.html

一、递归复习

1.什么是递归:函数内部自己调用自己

2.递归的特点

  • 必须有一个明确的结束条件
  • 每次进入更深一层递归时,问题规模相比上次递归都应有所减少
  • 递归效率不高,递归层次过多会导致栈溢出

3.看函数说结果

 1 def func1(x):
 2     print(x)
 3     func1(x-1)
 4 func1(5)
 5 # 一直打印到限制次数(无出口)
 6 
 7 def func2(x):
 8     if x > 0:
 9         print(x)
10         func2(x+1)
11 func2(5)
12 # 一直打印到限制次数(无出口)
13 
14 def func3(x):
15     if x > 0:
16         print(x)
17         func3(x-1)
18 func3(5) 
19 # 从5打印到1
20 
21 def func4(x):
22     if x > 0:
23         func4(x-1)
24         print(x)
25 func4(5)
26 # 从1打印到5

4.经典递归

(1)汉诺塔问题

解决思路:

假设有n个盘子:

  • 1.把n-1个圆盘从A经过C移动到B
  • 2.把第n个圆盘从A移动到C
  • 3.把n-1个小圆盘从B经过A移动到C

1:

2:

3:

 代码:

 1 def hanoi(a, b, c, n):
 2     if n == 1:
 3         print(a, "->", c)       # 将n-1个盘子从a经过c移动到b
 4     else:
 5         hanoi(a, c, b, n-1)     # 将剩余的最后一个盘子从a移动到c
 6         print(a, "->", c)
 7         hanoi(b, a, c, n-1)     # 将n-1个盘子从b经过a移动到c
 8 
 9 
10 hanoi('柱子a', '柱子b', '柱子c', 4)

总结:汉诺塔移动次数的递推式:h(x)=2h(x-1)+1

(2)字符串逆序输出

1 def rvs(s):
2     if s == "":
3         return s
4     else:
5         return rvs(s[1:]) + s[0]
6 
7 
8 s = rvs("Hello, Python")
9 print(s)

5.尾递归

二、常用算法

1.什么是算法

算法就是一个计算过程,解决问题的方法

算法(Algorithm)是指解题方案的准确而完整的描述,是一系列解决问题的清晰指令,算法代表着用系统的方法描述解决问题的策略机制。也就是说,能够对一定规范的输入,在有限时间内获得所要求的输出。如果一个算法有缺陷,或不适合于某个问题,执行这个算法将不会解决这个问题。不同的算法可能用不同的时间、空间或效率来完成同样的任务。一个算法的优劣可以用空间复杂度与时间复杂度来衡量

一个算法应该具有以下七个重要的特征:

  • 有穷性(Finiteness):算法的有穷性是指算法必须能在执行有限个步骤之后终止
  • 确切性(Definiteness):算法的每一步骤必须有确切的定义
  • 输入项(Input):一个算法有0个或多个输入,以刻画运算对象的初始情况,所谓0个输     入是指算法本身定出了初始条件
  • 输出项(Output):一个算法有一个或多个输出,以反映对输入数据加工后的结果。没       有输出的算法是毫无意义的
  • 可行性(Effectiveness):算法中执行的任何计算步骤都是可以被分解为基本的可执行       的操作步,即每个计算步都可以在有限时间内完成(也称之为有效性)
  • 高效性(High efficiency):执行速度快,占用资源少
  • 健壮性(Robustness):对数据响应正确

2.时间复杂度及空间复杂度

(1)时间复杂度

 1 print("hello, world")
 2 
 3 for i in range(n):
 4     print("hello, world")
 5 
 6 for i in range(n):
 7     for j in range(n):
 8         print("hello, world")
 9 
10 for i in range(n):
11     for j in range(n):
12         for k in range(n):
13             print("hello, world")    

问以上代码的运行时间谁最短?用什么方法来提现代码(算法)的运行快慢呢?答案就是用时间复杂度来衡量

常见算法的时间复杂度(由小到大排列):O(1)  O(logn)  O(n)  O(nlogn)  O(n^2) O(n^2logn)  O(n^3)

实例:

 1 print('hello world')
 2 print('hello python')   # O(1)    大O,可以认为它的含义是“order of”(大约是)
 3 
 4 n= 64
 5 while n>1:
 6     print(n)     # O(logn)  # n=64是输出依次为: 64 32 16 8 4 2 
 7     n = n//2
 8 
 9 for i in range(n):
10     print(i)      # O(n)
11 
12 for i in range(n):
13     for j in range(n):
14         print('hello world')   # O(n^2)
15 
16 for i in range(n):
17     for j in range(n):
18         for k in range(n):
19             print('hello world')   # O(n^3)

注:切片的复杂度是O(n) ,因为切的时候是赋值

总结:

  • 时间复杂度是用来估计算法运行时间的一个式子(单位)
  • 一般来说,时间复杂度高的算法比算法时间复杂度低的算法慢
  • 循环减半的过程就是O(logn),几次循环就是n的几次方的复杂度

(2)空间复杂度

空间复杂度是用来评估算法内存占用大小的一个式子,常见的空间复杂度:O(1)  O(n)  O(n^2)

空间换时间:计算机的资源很充足,可以用空间的消耗来换取一定的时间

3.常用查找

(1)列表查找

列表查找:从列表中查找指定元素

输入:列表、待查找的元素,输出:元素下标或未查找到元素

列表查找的方法:顺序查找和二分查找

  • 顺序查找:从列表第一个元素开始,顺序进行搜索直到找到为止
  • 二分查找:从有序列表的后续区开始查找,通过对查找的值和候选区中间的值进行比较,使候选区减半

以上两种查找的代码如下:

# 顺序查找 时间复杂 O(n)
def linear_search(find, data_list):
    for i in range(len(data_list)):
        if data_list[i] == find:
            return i
    return -1


# 二分查找 时间复杂 O(logn)
def binary_search(find, data_list):
    low = 0
    high = len(data_list)
    while low <= high:
        mid = (low + high) // 2
        # 找到find
        if data_list[mid] == find:
            return mid
        # find在左半边
        elif data_list[mid] > find:
            high = mid - 1
        # find在右半边
        else:
            low = mid + 1
    # 未找到find返回-1
    return -1

(2)查找练习

现在有一个学员信息列表(按id增序排列),格式为:

1 [
2     {"id": 1001, "name": "张三", "age": 20},
3     {"id": 1002, "name": "woz", "age": 22},
4     {"id": 1003, "name": "alex", "age": 23},
5     {"id": 1004, "name": "hf", "age": 26},
6     {"id": 1005, "name": "kk", "age": 27},
7 ]

现在要求修改二分查找代码,输入学生id,输出该学生在该列表下的下标并输出完整的学生信息

实现代码如下:

 1 import random
 2 stu_info = []       # 存储学生信息的列表
 3 
 4 # 随机生成n个数据
 5 def random_list(n):
 6     ids = list(range(1001, 1001+n))
 7     n1 = ["", "", "", "", "", ""]
 8     n2 = ["", "", "",  "", ""]
 9     n3 = ['', '', ""]
10     for i in range(n):
11         stu_age = random.randint(20, 30)
12         stu_id = ids[i]
13         stu_name = random.choice(n1)+random.choice(n2)+random.choice(n3)
14         stu_info.append({"id": stu_id, "age": stu_age, "name":stu_name})
15 
16 # 二分查找
17 def bin_search(data_set, find):
18     low = 0
19     high = len(data_set) - 1
20     while low <= high:
21         mid = (low+high)//2
22         if data_set[mid]["id"] == find:
23             return mid
24         elif data_set[mid]["id"] < find:
25             low = mid + 1
26         else:
27             high = mid - 1
28     return -1
29 
30 # 搜索信息
31 def search_info(info, find):
32     res = bin_search(info, find)
33     if res == -1:
34         print("没有找到")
35     else:
36         print(info[res])
37 
38 
39 random_list(15)
40 print("以下是所有学生的id信息: ")
41 # print(stu_info)
42 for item in stu_info:
43     print(item["id"], end=" ")
44 sid = int(input("\n请输入你想要查找的学生的id: ").strip())
45 search_info(stu_info, sid)

4.常用排序

常用的排序有以下几种:

三、常用数据结构

四、python cookbook算法与数据结构整理

猜你喜欢

转载自www.cnblogs.com/wyb666/p/8990024.html