Skip to content

Commit a4e05df

Browse files
committed
upload all notes
1 parent e6c4524 commit a4e05df

11 files changed

+2320
-1
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# data_structures_and_algorithms_python_note
22
数据结构和算法笔记📒
33

4-
YouTube教程的学习笔记[教程](https://www.youtube.com/watch?v=JFRKMzmapQk&list=PLC664nq_h8b_q8Hjq_q8fbst1TO1AKKz-)
4+
YouTube教程的学习笔记 [教程](https://www.youtube.com/watch?v=JFRKMzmapQk&list=PLC664nq_h8b_q8Hjq_q8fbst1TO1AKKz-)
55

66
后面还会加新开始看书的笔记
7+
Lines changed: 307 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,307 @@
1+
# 数据结构和算法(Python)
2+
[教材](https://jackkuo666.github.io/Data_Structure_with_Python_book/chapter2/section2.html)
3+
[教材](https://pegasuswang.github.io/python_data_structures_and_algorithms/)
4+
5+
[视频课](https://www.youtube.com/watch?v=ROzdRsYSp7k&list=PLC664nq_h8b_q8Hjq_q8fbst1TO1AKKz-&index=4)
6+
7+
## 01什么是算法
8+
算法就是计算机处理信息的本质,因为计算机程序的本质就是一个算法来高速计算机确切的步骤来执行一个指定的任务。
9+
算法是独立存在的解决问题的方法和思 想,实现的语言不重要
10+
11+
算法的5特性:
12+
输入:0或多个
13+
输出:至少一个
14+
有穷性:算法有限的步骤之后不会无限循环,并且在可以接受的时间内完成
15+
确定性:算法中的每一步都有确定的含义
16+
可行性:每一步都是可行的,也就是都能执行有限的次数完成
17+
18+
教材:数据结构与算法:python语言描述
19+
进阶:算法导论(更深,重点学思想
20+
21+
22+
```python
23+
import time
24+
start_time = time.time()
25+
for a in range(0,1001):
26+
for b in range(0,1001):
27+
for c in range(0,1001):
28+
if a**2+b**2 == c**2 and a+b+c ==1000:
29+
print("a, b, c: %d, %d, %d" % (a,b,c))
30+
end_time = time.time()
31+
print("Duration: %d" %(end_time-start_time))
32+
print("finished")
33+
```
34+
35+
a, b, c: 0, 500, 500
36+
a, b, c: 200, 375, 425
37+
a, b, c: 375, 200, 425
38+
a, b, c: 500, 0, 500
39+
Duration: 682
40+
finished
41+
42+
43+
改进: 因为a,b 确定下来c也就确定了
44+
45+
46+
```python
47+
import time
48+
start_time = time.time()
49+
for a in range(0,1001):
50+
for b in range(0,1001):
51+
c = 1000-a-b
52+
if a**2+b**2 == c**2:
53+
print("a, b, c: %d, %d, %d" % (a,b,c))
54+
end_time = time.time()
55+
print("Duration: %f" %(end_time-start_time))
56+
print("finished")
57+
```
58+
59+
a, b, c: 0, 500, 500
60+
a, b, c: 200, 375, 425
61+
a, b, c: 375, 200, 425
62+
a, b, c: 500, 0, 500
63+
Duration: 0.905913
64+
finished
65+
66+
67+
## 02 算法效率衡量
68+
69+
时间复杂度与大O表示法<br>
70+
单靠运行时间不可信不客观:和电脑新旧,运算能力有关<br>
71+
**时间复杂度:描述算法时间上的效率<br>**
72+
假定执行算法每一个基本操作的时间是固定的,**执行的<u>基本运算数量</u>**可以忽略机器环境的影响客观的反映算法的时间效率<br>
73+
**"大O表示法"<br>**
74+
> 时间复杂度:假设存在函数g,似的算法A处理规模为n的问题实力所用的时间为T(n)=O(g(n)),则称O(g(n))为算法A的监禁时间复杂度,简称为时间复杂度,记为T(n)<br>
75+
76+
计量算法基本操作的规模函数中的常量因子可以忽略不计
77+
78+
79+
## 03 最坏时间复杂度
80+
81+
分析算法时,存在几种可能的考虑:
82+
83+
算法完成工作最少需要多少基本操作,即最优时间复杂度:没啥意义<br>
84+
算法完成工作最多需要多少基本操作,即**最坏时间复杂度**:一种保证,通常时间复杂度就是指最坏这个<br>
85+
算法完成工作平均需要多少基本操作,即平均时间复杂度:全面评价,但没有保证<br>
86+
87+
##总结:
88+
89+
1. 基本操作,即只有常数项,认为其时间复杂度为O(1)
90+
2. 顺序结构,时间复杂度按加法进行计算
91+
3. 循环结构,时间复杂度按乘法进行计算
92+
4. 分支结构,时间复杂度取最大值 (比如if else)
93+
5. 判断一个算法的效率时,往往只需要关注操作数量的最高次项,其它次要项和常数项可以忽略
94+
6. 在没有特殊说明时,我们所分析的算法的时间复杂度都是指最坏时间复杂度
95+
96+
## 最常见的时间复杂度
97+
98+
99+
| 执行次数函数举例 || 非正式术语 |
100+
| :--------------- | :------- | :--------- |
101+
| 12 | O(1) | 常数阶 |
102+
| 2n+3 | O(n) | 线性阶 |
103+
| $3n^2+2n+1$ | $O(n^2)$ | 平方阶 |
104+
| 5log2n+20 | O(logn) | 对数阶 |
105+
| 2n+3nlog2n+19 | O(nlogn) | nlogn阶 |
106+
| $6n^3+2n^2+3n+4$ | $O(n^3)$ | 立方阶 |
107+
| $2^n $ | $O(2^n)$ | 指数阶 |
108+
109+
110+
注意,经常将log2n(以2为底的对数)简写成logn
111+
112+
**必须记住:**
113+
$O(1) < O(logn) < O(n) < O(nlogn) < O(n^2)< O(n^2logn) < O(n^3) < O(2^n) < O(n!) < O(n^n)$
114+
115+
116+
117+
## Python 内置类型性能分析 -- timeit
118+
119+
> 列表生成式<br>
120+
> Python内置的一种极其强大的生成列表 list 的表达式。返回结果必须是列表。
121+
122+
>基本语法:
123+
124+
```[ 变量表达式 for 变量 in 表达式 ]```
125+
126+
127+
```python
128+
#对比四种list列表构造方式的效率
129+
130+
from timeit import Timer
131+
132+
def test1(): #append()
133+
l = []
134+
for i in range(10000):
135+
l.append(i)
136+
137+
def test2(): #+=
138+
l = []
139+
for i in range(10000):
140+
l += [i]
141+
142+
def test2_1(): #+
143+
l = []
144+
for i in range(10000):
145+
l = l + [i]
146+
147+
def test3(): #列表生成式 [i for i in range]
148+
l = [i for i in range(10000)]
149+
150+
def test4(): #可迭代对象直接生成列表 list(range)
151+
l = list(range(10000))
152+
153+
def test5(): #extend()
154+
l = []
155+
for i in range(10000):
156+
l.extend([i])
157+
158+
159+
160+
161+
162+
timer1= Timer("test1()","from __main__ import test1")
163+
print("append():",timer1.timeit(number=1000),"seconds")
164+
165+
timer2= Timer("test2()","from __main__ import test2" )
166+
print("+=:",timer2.timeit(number=1000),"seconds")
167+
168+
timer2_1= Timer("test2_1()","from __main__ import test2_1" )
169+
print("+:",timer2_1.timeit(number=1000),"seconds")
170+
171+
timer3= Timer("test3()","from __main__ import test3" )
172+
print("[i for i in range]:",timer3.timeit(number=1000),"seconds")
173+
174+
timer4= Timer("test4()","from __main__ import test4" )
175+
print("list(range):",timer4.timeit(number=1000),"seconds")
176+
177+
timer5= Timer("test5()","from __main__ import test5" )
178+
print("extend():",timer5.timeit(number=1000),"seconds")
179+
```
180+
181+
append(): 0.64611264999985 seconds
182+
+=: 0.6851804809998612 seconds
183+
+: 112.89560661899986 seconds
184+
[i for i in range]: 0.2947488119998525 seconds
185+
list(range): 0.1802340100002766 seconds
186+
extend(): 0.9059880499999053 seconds
187+
188+
189+
可以看出:光用+很费时间,可以选择使用+= or extend()替换
190+
191+
## insert 和 append 比较
192+
193+
> list.insert(pos, elmnt)
194+
195+
196+
```python
197+
198+
def test1(): #append()
199+
l = []
200+
for i in range(10000):
201+
l.append(i) #尾部添加
202+
203+
204+
def test6(): #extend()
205+
l = []
206+
for i in range(10000):
207+
l.insert(0, i) #头部添加
208+
209+
timer1= Timer("test1()","from __main__ import test1")
210+
print("append():",timer1.timeit(number=1000),"seconds")
211+
212+
timer6= Timer("test6()","from __main__ import test6" )
213+
print("insert():",timer6.timeit(number=1000),"seconds")
214+
```
215+
216+
append(): 0.6008801650004898 seconds
217+
insert(): 19.97815154900036 seconds
218+
219+
220+
**从结果可以看出,append从尾端添加元素效率远远高于insert从顶端添加元素**<br>
221+
原因: 由于列表list的数据存储[方式决定的<br>
222+
223+
224+
**list内置操作的时间复杂度**
225+
226+
操作 | 平均时间复杂度 |
227+
--------------------------------------|----------------|
228+
list[index] | O(1) |
229+
list.append | O(1) |
230+
list.insert | O(n) |
231+
list.pop(index), default last element | O(1) |
232+
list.remove | O(n) |
233+
234+
235+
236+
lndex:O(1)
237+
append: O(1)
238+
contain(in): O(n)查找
239+
240+
**dict内置操作的时间复杂度**
241+
242+
![替代文字](https://i.loli.net/2021/10/20/Me3zXT8G56CpwEO.png)
243+
244+
## 数据结构
245+
246+
算法关注的是问题的解决步骤,没有关注处理的是什么样的数据
247+
248+
>我们如何用Python中的类型来保存一个班的学生信息? 如果想要快速的通过学生姓名获取其信息呢?
249+
250+
    实际上当我们在思考这个问题的时候,我们已经用到了数据结构。列表和字典都可以存储一个班的学生信息,但是想要在列表中获取一名同学的信息时,就要遍历这个列表,其时间复杂度为O(n),而使用字典存储时,可将学生姓名作为字典的键,学生信息作为值,进而查询时不需要遍历便可快速获取到学生信息,其时间复杂度为O(1)
251+
252+
253+
**概念**
254+
255+
    数据结构是计算机存储、组织数据的方式。数据结构是指相互之间存在一种或多种特定关系的数据元素的集合。
256+
257+
简而言之:一组数据如何保存
258+
259+
基本数据类型: float、int, char...<br>
260+
所以list, dict...已经是一种高级的数据结构了
261+
262+
## 算法与数据结构的区别
263+
264+
程序 = 数据结构 + 算法
265+
266+
算法:为解决实际问题设计的<br>
267+
数据结构: 算法处理问题的载体
268+
269+
## 抽象数据类型(ADT:Abstract Data Type)
270+
271+
定义:一个数学模型以及定义在此数学模型上的一组操作
272+
273+
例子:
274+
275+
先规定好数据如何保存(数据结构),定义这些数据结构支持的操作(具体怎么实现不去管)
276+
277+
```
278+
class students(object):
279+
280+
def adds
281+
def pop
282+
def sort
283+
def ...
284+
```
285+
286+
287+
288+
289+
```python
290+
a = [1, 2]
291+
a *=10
292+
print(a)
293+
294+
295+
```
296+
297+
[1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2]
298+
299+
最常用的数据运算有五种:
300+
301+
```
302+
插入
303+
删除
304+
修改
305+
查找
306+
排序
307+
```
Binary file not shown.

0 commit comments

Comments
 (0)