一、基础概念
(1)定义
算法(Algorithm)是一个有穷规则(或语句、指令)的有序集合。
它确定了解决某一问题的一个运算序列。对于问题的初始输入,通过算法有限步的运行,产生一个或多个输出。
数据的逻辑结构与存储结构密切相关:
算法设计: 取决于选定的逻辑结构
算法实现: 依赖于采用的存储结构
(2)算法的特性
有穷性
—— 算法执行的步骤(或规则)是有限的;
确定性
—— 每个计算步骤无二义性;
可行性
—— 每个计算步骤能够在有限的时间内完成;
输入 输出
—— 存在数据的输入和出输出
(3)评价算法好坏的方法
正确性:
运行正确是一个算法的前提。
可读性:
容易理解、容易编程和调试、容易维护。
健壮性:
考虑情况全面,不容以出现运行错误。
时间效率高:
算法消耗的时间少。
储存量低:
占用较少的存储空间。
二、时间复杂度计算
算法效率——用依据该算法编制的程序在计算机上执行所消耗的时间来度量。“O”表示一个数量级的概念。根据算法中语句执行的最大次数(频度)来 估算一个算法执行时间的数量级。
计算方法:
写出程序中所有运算语句执行的次数,进行加和
如果得到的结果是常量则时间复杂度为1
如果得到的结果中存在变量n则取n的最高次幂作为时间复杂度
下图表示随问题规模n的增大,算法执行时间的增长率。
三、排序和查找
3.1 排序
排序(Sort)是将无序的记录序列(或称文件)调整成有序的序列。
常见排序方法:
(1)冒泡排序
冒泡排序是一种简单的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。
(2)选择排序
工作原理为,首先在未排序序列中找到最小元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小元素,然后放到排序序列末尾。以此类推,直到所有元素均排序完毕。
(3)插入排序
对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。插入排序在实现上,通常在从后向前扫描过程中,需要反复把已排序元素逐步向后挪位,为最新元素提供插入空间。
(4)快速排序
从数列中挑出一个元素,称为 “基准”(pivot),重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作。递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。
排序代码实现:
1 """
2 sort.py 排序算法训练
3 """
4
5 # 冒泡
6 def bubble(list_):
7 n = len(list_)
8 # 外层表示比较多少轮
9 for i in range(n - 1):
10 # 表示每轮两两比较的次数
11 for j in range(n - 1 - i):
12 # 从小到大排序
13 if list_[j] > list_[j + 1]:
14 list_[j],list_[j + 1] = list_[j + 1],list_[j]
15
16 # 完成一轮交换
17 def sub_sort(list_,low,high):
18 # 选定基准
19 x = list_[low]
20 # low向后 high向前
21 while low < high:
22 # 后面的数往前放
23 while list_[high] >= x and high > low:
24 high -= 1
25 list_[low] = list_[high]
26 # 前面的数往后放
27 while list_[low] < x and low < high:
28 low += 1
29 list_[high] = list_[low]
30
31 list_[low] = x
32 return low
33
34
35 def quick(list_,low,high):
36 # low 表示列表第一个元素索引,high表示最后一个元素索引
37 if low < high:
38 key = sub_sort(list_,low,high)
39 quick(list_,low,key - 1)
40 quick(list_, key + 1,high)
41
42
43
44 l = [4,9,3,1,2,5,8,4]
45 # bubble(l)
46 quick(l,0,len(l)-1)
47 print(l)
1 """
2 sort.py 排序算法训练
3 """
4
5 # 冒泡
6 def bubble(list_):
7 n = len(list_)
8 # 外层表示比较多少轮
9 for i in range(n - 1):
10 # 表示每轮两两比较的次数
11 for j in range(n - 1 - i):
12 # 从小到大排序
13 if list_[j] > list_[j + 1]:
14 list_[j],list_[j + 1] = list_[j + 1],list_[j]
15
16 # 完成一轮交换
17 def sub_sort(list_,low,high):
18 # 选定基准
19 x = list_[low]
20 # low向后 high向前
21 while low < high:
22 # 后面的数往前放
23 while list_[high] >= x and high > low:
24 high -= 1
25 list_[low] = list_[high]
26 # 前面的数往后放
27 while list_[low] < x and low < high:
28 low += 1
29 list_[high] = list_[low]
30
31 list_[low] = x
32 return low
33
34
35 def quick(list_,low,high):
36 # low 表示列表第一个元素索引,high表示最后一个元素索引
37 if low < high:
38 key = sub_sort(list_,low,high)
39 quick(list_,low,key - 1)
40 quick(list_, key + 1,high)
41
42
43 # 选择排序
44 def select(list_):
45 # 没轮选出一个最小值,需要 len(list_) - 1 轮
46 for i in range(len(list_) - 1):
47 min = i # 假设 list_[i] 为最小值
48 for j in range(i + 1,len(list_)):
49 if list_[min] > list_[j]:
50 min = j # 擂主换人
51 # 进行交换,将最小值换到应该在的位置
52 if min != i:
53 list_[i],list_[min] = list_[min],list_[i]
54
55 # 插入排序
56 def insert(list_):
57 # 控制每次比较的数是谁,从第二个数开始
58 for i in range(1,len(list_)):
59 x = list_[i] # 空出list_[i]的位置
60 j = i - 1
61 while j >= 0 and list_[j] > x:
62 list_[j + 1] = list_[j]
63 j -= 1
64 list_[j + 1] = x
65
66
67 l = [4,9,3,1,2,5,8,4]
68 # bubble(l)
69 # quick(l,0,len(l)-1)
70 # select(l)
71 insert(l)
72
73 print(l)
3.2 查找
查找(或检索)是在给定信息集上寻找特定信息元素的过程。
二分法查找:
当数据量很大适宜采用该方法。采用二分法查找时,数据需是排好序的。
代码实现:
1 """
2 search.py 二分查找方法训练
3 """
4
5 # list_为有序数列,key为要查找的关键值,返回key在数列中的索引号
6 def search(list_,key):
7 # 第一个数index 最后一个数index
8 low,high = 0,len(list_) - 1
9
10 # 循环每次去除一半内容
11 while low <= high:
12 mid = (low + high) // 2
13 # 取后半部分
14 if list_[mid] < key:
15 low = mid + 1
16 # 取前半部分
17 elif list_[mid] > key:
18 high = mid - 1
19 else:
20 return mid
21
22
23 l = [1,2,3,4,5,6,7,8,9,10]
24 print("Key index:",search(l,10))