>python数据结构与算法学习路线
>学习内容:
>- 基本算法:枚举、排序、搜索、递归、分治、优先搜索、贪心、双指针、动态规划等...
>- 数据结构:字符串(string)、列表(list)、元组(tuple)、字典(dictionary)、集合(set)、数组、队列、栈、树、图、堆等...
目录
基础语法
1. python中缩进可以根据喜好来,但是选定一种必须保持一致
2. 注释:# 或 ''' '''
ctrl+/注释多行
3. 赋值 =
4. 判断等 ==
5. 命名:大小写敏感,字母或者下划线开头,可以包含字母下划线数字,不能与保留字相同
五大数据类型
一、字符串 string
1. 表示方法
单引号,双引号,三引号 ,例如:a="welcome"
2. 使用方法
1. 索引(取单个字符串)
<字符串>[]
eg : t = " 50f "
t [-1] = " f "
2. 切片
<字符串>[M:N]
取M到N-1
<字符串>[M:N:2]
取M到N-1,步长为2
3. 常用的str的方法
- string.capitalize() 把字符串的第一个字符大写
- string.count(str, beg=0, end=len(string)) 返回 str 在 string 里面出现的次数,如果 beg 或者 end 指定则返回指定范围内 str 出现的次数
- string.endswith(obj, beg=0, end=len(string)) 检查字符串是否以 obj 结束,如果beg 或者 end 指定则检查指定的范围内是否以 obj 结束,如果是,返回 True,否则返回 False.
- string.find(str, beg=0, end=len(string)) 检测 str 是否包含在 string 中,如果 beg 和 end 指定范围,则检查是否包含在指定范围内,如果是返回开始的索引值,否则返回-1
- string.index(str, beg=0, end=len(string)) 跟find()方法一样,只不过如果str不在 string中会报一个异常.
- string.isalnum() 如果 string 至少有一个字符并且所有字符都是字母或数字则返回 True,否则返回 False
- string.isalpha() 如果 string 至少有一个字符并且所有字符都是字母则返回 True,否则返回 False
- string.isdecimal() 如果 string 只包含十进制数字则返回 True 否则返回 False.
- string.isdigit() 如果 string 只包含数字则返回 True 否则返回 False.
- string.islower() 如果 string 中包含至少一个区分大小写的字符,并且所有这些(区分大小写的)字符都是小写,则返回 True,否则返回 False
- string.isnumeric() 如果 string 中只包含数字字符,则返回 True,否则返回 False
- string.isspace() 如果 string 中只包含空格,则返回 True,否则返回 False.
- string.istitle() 如果 string 是标题化的(见 title())则返回 True,否则返回 False
- string.isupper() 如果 string 中包含至少一个区分大小写的字符,并且所有这些(区分大小写的)字符都是大写,则返回 True,否则返回 False
- string.join(seq) 以 string 作为分隔符,将 seq 中所有的元素(的字符串表示)合并为一个新的字符串
- string.lower() 转换 string 中所有大写字符为小写.
- string.lstrip() 截掉 string 左边的空格
- max(str) 返回字符串 str 中最大的字母。
- min(str) 返回字符串 str 中最小的字母。
- string.replace(str1, str2, num=string.count(str1)) 把 string 中的 str1 替换成 str2,如果 num 指定,则替换不超过 num 次.
- string.split(str="", num=string.count(str)) 以 str 为分隔符切片 string,如果 num 有指定值,则仅分隔 num+ 个子字符串
- string.startswith(obj, beg=0,end=len(string)) 检查字符串是否是以 obj 开头,是则返回 True,否则返回 False。如果beg 和 end 指定值,则在指定范围内检查.
- string.strip([obj]) 在 string 上执行 lstrip()和 rstrip()
- string.swapcase() 翻转 string 中的大小写
- string.title() 返回"标题化"的 string,就是说所有单词都是以大写开始,其余字母均为小写(见 istitle())
- string.translate(str, del="") 根据 str 给出的表(包含 256 个字符)转换 string 的字符,要过滤掉的字符放到 del 参数中
- string.upper() 转换 string 中的小写字母为大写
二、列表 list
1. 表示方法
[ ]表示用逗号隔开,列表中的元素可以各不相同,可以是任意类型,例如:
- a = ["F","f"]
- a = [10,20,'abc',True]
2. 使用方法
3. 函数
- 使用in判断是否在列表中,在返回真,不在返回假
- 类型之间转换:eval()去掉最外侧的引号,字符串类型转换成数字或字母
- range() : 可以非常方便的创建整数列表,语法格式为:range([start,] end [,step])
- + 运算符操作
并不是真正的尾部添加元素, 而是创建新的列表对象, 将原列表的元素和新列表的元素依次复制到新的列表对象中, 对于操作大量元素不建议使用。 - 切片操作
切片是 Python 序列及其重要的操作,适用于列表、元组、字符串等等。切片的格式如下:[起始偏移量 start:终止偏移量 end[:步长 step]]
二维切片:
data = [tmp[1:] for tmp in data ]
三、字典 dict
1. 表示方法
a = { 'name' : 'gaoqi' , 'age' : 18 , 'job' : 'programmer' }
2. 使用方法
创建字典 | 输出 |
a = { } 或 a = dict() | { }创建空的字典 |
a = {'name' : 'zmy','age' : 22} | {'name' : 'zmy','age' : 22} |
dict(name= 'zmy' ,age= 22) | {'name' : 'zmy','age' : 22} |
dict([('name','zmy') ,('age', 22)]) | {'name' : 'zmy','age' : 22} |
k = ['name','age'] v = ['zmy',22] dict(zip(k,v)) | {'name' : 'zmy','age' : 22} |
dict.fromkeys(['name','age']) | {'name' : None,'age' : None}创建值为空的字典 |
字典元素的访问 | 输出 |
a['name'] | zmy若键不存在,则抛出异常 |
a.get('name') a.get('sex','男') | zmy 男 (键不存在返回 None,也可以设定指定键不存在时默认返回的对象) |
a.items() | dict_items([('name','zmy'),('age',22)]) |
a.keys() | dict_keys(['name','age']) |
a.values() | dict_values(['zmy',22]) |
增删改 | 作用 | 说明 | 输出 |
a['money'] = 10000 | 增加 | 如果“键”已经存在,则覆盖旧的键值对;如果“键”不存在,则新增“键值对” | {'name' : 'zmy','age' : 22,'money':10000} |
a={'name' : 'zmy','age' : 22} b={'name' : 'zmy1','money':10000} a.update(b) | 更新 | 将新字典中所有键值对全部添加到旧字典对象上。如果 key 有重复,则直接覆盖。 | {'name' : 'zmy1','age' : 22,'money':10000} |
del(a['name']) b = a.pop('age') | 删除 | 可以使用 del()方法;或者 clear()删除所有键值对;pop()删除指定键值对,并返回对应的“值对象” | {'age',22} 22 |
a.popitem() | 随机删除 | 随机删除和返回该键值对 | 若想一个接一个地移除并处理项,这个方法就非常有效(因为不用首先获取键的列表)。 |
字典核心底层原理(重要)
字典对象的核心是散列表。散列表是一个稀疏数组(总是有空白元素的数组),数组的每个单元叫做 bucket。每个 bucket 有两部分:一个是键对象的引用,一个是值对象的引用。由于所有 bucket 结构和大小一致,我们可以通过偏移量来读取指bucket。
将一个键值对放进字典的底层过程
假设字典 a 对象创建完后,数组长度为 7:
我要把”name”=”gaochenxi”这个键值对放到字典对象 a 中,第一步需要计算键”name”的散列值。Python 中通过 hash()来计算。
由于数组长度为 7,我们可以拿计算出的散列值的最右边 3 位数字作为偏移量,即“000”,十进制是数字 0。我们查看偏移量 0,对应的 bucket 是否为空。如果为空,则将键值对放进去。如果不为空,则依次取右边 3 位作为偏移量,即“010”,十进制是数字
2。再查看偏移量为 2 的 bucket 是否为空。直到找到为空的 bucket 将键值对放进去。流程图如下:
扩容
python 会根据散列表的拥挤程度扩容。“扩容”指的是:创造更大的数组,将原内容拷贝到新数组中。接近 2/3 时,数组就会扩容。
根据键查找“键值对”的底层过程
当我们调用 a.get(“name”),就是根据键“name”查找到“键值对”,从而找到值对象“gaochenxi”。
第一步,我们仍然要计算“name”对象的散列值:
和存储的底层流程算法一致,也是依次取散列值的不同位置的数字。 假设数组长度为7,我们可以拿计算出的散列值的最右边 3 位数字作为偏移量,即“00”,十进制是数字0。我们查看偏移量 0,对应的 bucket 是否为空。如果为空,则返回 None。如果不为空,则将这个 bucket 的键对象计算对应散列值,和我们的散列值进行比较,如果相等。则将对应“值对象”返回。如果不相等,则再依次取其他几位数字,重新计算偏移量。依次取完后,仍然没有找到。则返回 None。流程图如下:
用法总结:
1. 键必须可散列
(1) 数字、字符串、元组,都是可散列的。
(2) 自定义对象需要支持下面三点:
1支持 hash()函数
2支持通过__eq__()方法检测相等性。
3若 a==b 为真,则 hash(a)==hash(b)也为真。
2. 字典在内存中开销巨大,典型的空间换时间。
3. 键查询速度很快
4. 往字典里面添加新建可能导致扩容,导致散列表中键的次序变化。因此,不要在遍历字典的同时进行字典的修改。
参考博主:待烟火清凉,自学使用侵删
四、元祖 tuple
1. 表示方法
a = (10,20,30) 或者 a = 10,20,30
如果元组只有一个元素, 则必须后面加逗号,因为解释器会把(1)解释为整数 1, (1,)解释为元组。
2. 使用方法
元组属于不可变序列,不能修改元组中的元素。因此元组没有增加元素、修改元素、删除元素相关的方法。
3. 函数
函数 | 描述 |
tuple() | 接收列表、字符串、其他序列类型、迭代器等生成元组 |
sorted(tupleObj) | 元组排序,因为不能修改原列表序列所以不能用 .sort |
zip(list1,list2,...) | 将多个列表对应位置的元素组合成为元组,并返回这个 zip 对象 |
元组的访问和处理速度比列表快
函数
1.print()
print("{:.2f}".format(c))
{}是一个槽,c中的东西满足{}中格式要求放进去显示
:.2f取小数点后两位
print(____ , end = " ")打印结果没有空格
2. input()
返回的数据是字符串格式
3. range()
range(N)
产生0到n-1共n个
range(m,n)
产生m到n-1的整数数列,共n-m个
基本结构
for while if def都有冒号
循环
for i in range(次数)
循环从0到次数-1
判断
常用三方库
引用方法:
法1:
import<库名>
<库名>.<函数名>
法2:
from <库名> import <函数名>
<函数名>
方法二可能会导致函数名重复
法3:给库起一个小名
import ___ as_
1.turtle
主要作用:画图
turtle.setup(宽度,高度,x,y)建立一个窗口
turtle.goto()无论在哪里到(x,y)坐标
turtle.seth()改变海龟的角度(绝对坐标的改变)
turtle.penup()抬起笔
turtle.pendown()放下笔
turtle.forward()往前走
turtle.circle(r,extent)半径为r,角度为extent,画圆
turtle.right()向右转
turtle.left()向左转
数值运算操作符
x/y
x//y除结果取整
+x
-x
x%y相除取余数
不同类型运算会生成一种最宽的类型
eg:整型->浮点型->复数型
以函数形式提供的数值运算功能:
abs(x)取绝对值
divmod(x,y)同时给出商和余数 eg:divmod(10,3)->(3,1)
pow(x,y,(,z))同时给出幂和余数(x**y)%z
内建函数和魔法函数
总结的很全面的魔法函数链接:11. (译)Python魔法方法指南 — 一起写Python文章,一起看Python文章
经常是两个下划线包围来命名的(比如 __init__ , __lt__ ),它通常是直接作用于某个类而不用特意调用,使得编程变得整洁干净