P90 集合课堂练习 2024/9/28
一、集合生成式
- 集合生成式就是"生成集合的公式"
- 基本语法:
{集合元素的表达式for 自定义变量 in 可迭代对象}
实例(set_create.py)说明:
{ ele * 2 for ele in range(1,5)}==>得到集合含有2,4,6,8这四个元素,
但是集合是无序的,所以不能保证元素的顺序一定是2,4,6,8
思考题:
{ ele + ele for ele in"韩顺平"}=得到集合==>
结果:
set1 = {ele * 2 for ele in range(1, 5)}
print("set1:", set1) # {8, 2, 4, 6}
set2 = {ele + ele for ele in "韩顺平"}
print("set2:", set2)
说明:大家注意观察:集合生成式和列表生成式的区别就在于,集合生成式使用
{}
,而列表生成式使用[]
二、课堂练习
# @Author :zjc
# @File :026_set_exercise.py
# @Time :2024/9/28 17:12
# 1、用三个集合表示三门学科的选课学生姓名(一个学生可以同时选多门课)
s_history = {"小明", "张三", "李四", "王五", "Lily", "Bob"}
s_politic = {"小明", "小花", "小红", "二狗"}
s_english = {"小明", "Lily", "Bob", "Davil", "李四"}
# 1. 求选课学生总共有多少人
"""
思路分析:
1. 对三个集合求并集【自动去重】
2. 对新的集合求len()
"""
student01 = s_history | s_politic | s_english
# student01 = s_history.union(s_politic, s_english)
print(f"选课学生总共有多少人:{len(student01)}")
# 2. 求只选了第一个学科的学生数量和学生名字
"""
思路分析:
1. 即求出只在s_history学院
2. 使用差集即可 s_history - s_politic - s_english
"""
print(f"只选了第一个学科的学生数量{len(s_history - s_politic - s_english)}"
f"学生姓名{s_history - s_politic - s_english}")
# 3. 求只选了一门学科的学生数量和学生名字
"""
1. 求出只选了history的学生
2. 求出只选了politic的学生
3. 求出只选了english的学生
4. 然后求出并集集合
"""
# 1、 求出只选了history的学生
s1 = s_history - s_politic - s_english
# 2、求出只选了politic的学生
s2 = s_politic - s_english - s_history
# 3、 求出只选了english的学生
s3 = s_english - s_history - s_politic
print(f"只选了一门学科的学生数量{len(s1 | s2 | s3)}和学生名字{s1 | s2 | s3}")
# 4. 求选了三门学科的学生数量和学生名字
"""
思路分析:
1. 求出即在s_politic 又在s_history还在s_english中的
2. 就是对三个集合求交集
"""
print(f"选了三门学科的学生数量{len(s_history & s_politic & s_english)}"
f"和学生名字{s_history & s_politic & s_english}")
P91 字典基本使用 2024/9/29
参考文档:https://docs.python.org/zh-cn/3.11/tutorial/datastructures.html#dictionaries
一、需求引出
思路分析:
1、目前这种需求是:通过xx查询yy的需求2、在编程中,我们通常称为基于Key查询Value场景需求,是经常遇到的,是一种映射关系
3、而前面学习的列表、元组、集合都是一种单值存储,处理映射关系就不方便了
4、解决方案->字典(dict)
二、基本介绍
- 字典(dict,完整的单词是dictionary)也是一种常用的 Python 数据类型,其他语言可能把字典称为联合内存或联合数组。
- 字典是一种映射类型,非常适合处理通过xx查询yy 的需求,这里的xx我们称为
Key(键/关键字)
,这里的yy 我们称为Value(值)
,即Key----Value的映射关系 - 龟叔为什么把这种映射类型,命名为字典,这个很有意思,示意图:
三、字典的定义
- 创建一个字典,只要把逗号分隔的不同的元素,用括起来即可,存储的元素是一个个的:键值对,示例:
dict_a= {key1:value, key2:value, key3:value... .}
-通过key取出对应的value语法:
字典名[key]
---->dict_a[key1]
- 字典使用基本案例:
# 字典的基本使用案例
# 定义字典:键值对
tel = {'jack': 4098, 'tom': 4139}
print(f"dict_tel: {tel}类型: {type(tel)}") # 查询jack 的tel <class 'dict'>
# 保证jack是可以查询到的
print("jack的tel:", tel['jack']) # 4098
四、注意事项和细节
- 字典的Key(关键字)通常是字符串或数值, Value可以是任意数据类型
- 参考:https://docs.python.org/zh-cn/3.11/tutorial/datastructures.html#dictionaries
dict_a = {
# 值为列表
"jack": [100, 200, 300],
# 值为元组
"mary": (10, 20, "hello"),
# 值为集合
"nono": {"apple", "pear"},
# 值为 字符串
"smith": "计算机老师",
# 值为 字典
"周星驰": {
"性别": "男",
"age": 18,
"地址": "香港"
},
"key1": 100,
"key2": 9.8,
"key3": True
}
print(f"dict_a: {dict_a}类型:{type(dict_a)}")
- 字典不支持索引,会报
KeyError
print(dict_a[0]) # 报错
- 既然字典不支持索引,所以对字典进行遍历不支持while,只支持for,注意直接对字典进行遍历,遍历得到是key。
# 3、既然字典不支持索引,所以对字典进行遍历不支持while,只支持for
dict_b = {'one': 1, 'two': 2, 'three': 3}
# 遍历方式1-依次取出key, 再通过dict[key]取出对应的value
print("----------遍历方式1----------")
for key in dict_b:
print(f"key:{key} value:{dict_b[key]}")
# 遍历方式2-依次取出value
# 仅取出值:
print("----------遍历方式2----------")
for value in dict_b.values():
print(f"value:{value}")
# 遍历方式3-依次取出key-value
# 一次性取出键和值:
print("----------遍历方式3----------")
for k,v in dict_b.items():
print(f"k :{k},va:{v}")
- 创建空字典可以通过
{}
,或者dict()
# 4、创建空字典可以通过{},或者dict()
dict_c = {}
dict_d = dict()
print(f"dict_c: {dict_c}类型:{type(dict_c)}")
print(f"dict_d: {dict_d}类型:{type(dict_d)}")
- 字典的
key
必须是唯一的,如果你指定了多个相同的key,后面的键值对套覆盖前面的。
dict_e = {'one': 1, 'two': 2, 'three ': 3, 'two': 200}
print(f"dict_e: {dict_e}") # {'one': 1, 'two': 200, 'three ': 3}
P92 字典常用操作 2024/9/30
一、常用操作一览
案例演示:
# @Author :zjc
# @File :029_dic_operations.py
# @Time :2024/9/30 15:58
"""
演示字典的常用操作
{ "one": 1,"two" : 2,"three" : 3}
"""
# 定义字典
dict_a = {"one": 1, "two": 2, "three": 3}
# 1 len(d):返回字典d 中的项数
print(f"dict_a 的元素个数是:{len(dict_a)}")
# 2 d[key]:返回d中以 key 为键的项。如果映射中不存在 key 则会引发keyError
print("key为three对应的value : ", (dict_a['three'])) # 3
# 3 d[key] = value:将d[key] 设为 value,如果key已经存在,则是修改value,
# 如果key没有存在,则是增加 key-value,注意会直接修改原来的字典-示意图
# 修改需求:修改key = 'one'对应的value为第一
dict_a["one"] = "第一" # 相当于之前的one被替换成“第一”
print(f"dic_a:{dict_a}")
# 添加需求:增加key为'four' value为4
dict_a["four"] = 4
print(dict_a)
# 4 del d[key]:将d[key] 从d中移除。如果映射中不存在key 则会引发KeyError
# 需求删除key为'four'的元素
del dict_a["four"]
print(f"dict_a: {dict_a}")
# 5 pop(key, default]) :
# 如果key存在于字典中则将其移除并返回其值,否则返回 default。
# 如果default未给出且 key不存在于字典中,则会引发KeyError
# 需求:将key为'one'的值返回,并将该元素从字典移除
# val = dict_a.pop("one~","哈哈") # 会返回默认“哈哈”
val = dict_a.pop("one") # 会移除元素并且返回其值
print(f"val: {val}")
print(f"dict_a: {dict_a}")
# 6 keys():返回字典所有的key
dict_a_keys = dict_a.keys()
print(f"dict_a_keys: {dict_a_keys}类型{type(dict_a_keys)}") # <class 'dict_keys'>
# 同样也可以取出来 for循环
for k in dict_a_keys:
print("k->", k)
# 7 key in d:如果d中存在键key则返回True,否则返回 False
# 需求:判断字典中是否有 key 'two '
print("two" in dict_a) # True
# 8 clear():移除字典中的所有元素#需求:将字典清空
dict_a.clear()
print(f"dict_a: {dict_a}")
二、字典生成式
1、看一个具体的需求给出了如下两个列表:
books =["红楼梦","三国演义","西游记","水浒传"]
authors =["曹雪芹","罗贯中","吴承恩","施耐庵"]
生成对应的字典:
{'红楼梦':'曹雪芹','三国演义':'罗贯中','西游记'":'吴承恩','水浒传':'施耐庵'}
2、内置函数
zip()
说明:zip()可以将可迭代的对象作为参数,将对象中对应的元素打包成一个元组,返回由这些元组组成的列表
字典生成式基本语法:
字典key的表达式:字典value的表达式 for 表示key的变量,表示value的变量 in zip(可迭代对象,可迭代对象)}
# 实例说明:
books = ["红楼梦", "三国演义", "西游记", "水浒传"]
authors = ["曹雪芹", "罗贯中", "吴承恩", "施耐庵"]
dict_a = {book: author for book, author in zip(books, authors)}
print("dict_book", dict_a)
# 思考题1:
str1 = "韩顺平"
dict_b = {ele1: ele2 * 2 for ele1, ele2 in zip(str1, str1)}
print("str1:", dict_b)
# 思考题2:
# 给出两个列表:
english_list = ["red", "black", "yellow", "white"]
chinese_list = ["红色", "黑色", "黄色", "白色"]
# 生成一个字典:
# {'红色': 'RED', '黑色': 'BLACK', '黄色': 'YELLOW', '白色': 'WHITE'}
dict_c = {ele1:ele2.upper() for ele1,ele2 in zip(chinese_list,english_list)}
print(dict_c)
P93 字典课堂练习 2024/9/30
一、课堂练习
- 解决之前的需求:
- 一个公司有多个员工,请使用合适的数据类型保存员工的信息(比如员工号、年龄、名字、入职时间、薪水等),
- 1、员工号是入职时分配的,唯一不重复
- 一个公司有多个员工,请使用合适的数据类型保存员工的信息(比如员工号、年龄、名字、入职时间、薪水等),
# @Author :zjc
# @File :031_dict_exercise.py
# @Time :2024/9/30 17:20
clerks = {"0001": {"age": 20,
"name": "贾宝玉",
"entry_time": "2011-11-11",
"sal": 12000
},
"O002": {"age": 21,
"name": "薛宝钗",
"entry_time": "2015-12-12",
"sal": 10000
},
"0010": {"age": 18,
"name": "林黛玉",
"entry_time": "2018-10-10",
"sal": 20000
}
}
# 2)通过员工号(0010),可以查询到员工的信息
print(f"员工号为0010的信息为:"
f"名字:{clerks["0010"]["name"]} "
f"年龄:{clerks["0010"]["age"]}"
f"入职时间:{clerks["0010"]["entry_time"]} "
f"薪水:{clerks["0010"]["sal"]}")
# 3)可以根据需要,可以动态的增加、删除员工,请演示添加和删除一个员工
# 增加:(员工号:0020,年龄:30,名字:老韩,入职时间:2020-08-10,薪水: 6000)
clerks["0020"] = {
"age": 30,
"name": "老韩",
"entry_time": "2020-8-10",
"sal": 6000
}
print(clerks)
# 删除:0001号员工
del clerks["0001"]
print("-" * 60)
print(clerks)
# 4)可以根据需要,可以修改员工的信息(比如年龄、名字、入职时间、薪水等),
# 请演示修改一个员工信息修改员工号为0020的,
# 名字:韩顺平,入职时间: 1999-10-10,薪水在原来的基础上增加10%
clerks["0020"]['name'] = '韩顺平'
clerks["0020"]['entry_time'] = '1999-10-10'
clerks["0020"]['sal'] += clerks["0020"]['sal'] * 0.1
print(clerks)
# 5)要求:遍历所有员工,把所有员工的薪水,在原工资的基础上,增加20%
keys = clerks.keys()
for key in keys:
clerks[key]['sal'] += clerks[key]['sal'] * 0.2
print("-" * 60)
print("clerks", clerks)
# 6)按照如下格式输出所有员工信息
# 员工号为??的信息如下年龄:??名字:??入职时间:??薪水:??
for key in keys:
print(f"员工号为{key}的信息如下 "
f"年龄:{clerks[key]['age']}"
f"名字:{clerks[key]['name']}"
f"入职时间:{clerks[key]['entry_time']}"
f"薪水:{clerks[key]['sal']}")
print("-" * 60)
for key in keys:
# 取出key的值,就是每个员工对应的信息,每个员工对应的所有信息就是第一个键的值
# 通过key得到员工的信息(字典)
clerks_info = clerks[key]
print(f"员工号为{key}的信息如下 "
f"年龄:{clerks_info['age']}"
f"名字:{clerks_info['name']}"
f"入职时间:{clerks_info['entry_time']}"
f"薪水:{clerks_info['sal']}")
P94 数据容器特点比较及小结 2024/10/1
一、数据容器特点比较
- 参考文档:[字典是否有序]https://blog.csdn.net/m0_46829545/article/details/128581541
二、通用序列操作
- 大多数序列类型,包括可变类型和不可变类型都支持下表中的操作:
三、通用转换操作
- 容器转用操作一览:
- 案例演示:
# @Author :zjc
# @File :032_container_convert.py
# @Time :2024/10/1 20:43
str_a = "hello"
list_a = ["jack", "tom", "mary"]
tuple_a = ("hsp", "tim")
set_a = {"red", "black"}
dict_a = {"O001": "小倩", "O002": "黑山老妖"}
# 1. list([iterable]):
# iterable 可以是序列、支持迭代的容器或其它可迭代对象,#也就是将指定的容器转成列表
print("-" * 60)
print(f"str_a转成list: {list(str_a)}") # ['h', 'e', 'l', 'l', 'o']
print(f"tuple_a转成list: {list(tuple_a)}") # ['hsp', 'tim']
print(f"set_a转成list: {list(set_a)}") # ['black', 'red']
print(f"dict_a转成list: {list(dict_a)}") # ['O001', 'O002']
# 2. str(容器)∶将指定的容器转成字串(相当于整体都转了,包含括号)
print("-" * 60)
print(f"list_a转成str: {str(list_a)}类型: {type(str(list_a))}")
print(f"tuple_a转成str->{str(tuple_a)}类型:{type(str(tuple_a))}")
print(f"set_a转成str->{str(set_a)}类型: {type(str(set_a))}")
print(f"dict_a转成str->{str(dict_a)}类型->{type(str(dict_a))}")
# 3. tuple([iterable]):
# iterable 可以是序列、支持迭代的容器或其他可迭代对象,也就是将指定容器转成元组
print("-" * 60)
print(f"str_a转成tuple->{tuple(str_a)}")
print(f"list_a转成tuple->{tuple(list_a)}")
print(f"set_a转成tuple->{tuple(set_a)}")
print(f"dict_a转成tuple->{tuple(dict_a)}")
# 4. set([iterable]):
# iterable可以是序列、支持迭代的容器或其他可迭代对象,#也就是将指定的容器转成集合
print("-" * 60)
print(f"str_a转成set: {set(str_a)}") # 自动去重
print(f"st_a转成set: {set(list_a)}")
print(f"tuple_a转成set: {set(tuple_a)}")
print(f"dict_a转成set: {set(dict_a)}")
四、其他操作说明
- 还有更多的方法,不可能全部学完,在需要用到的时候到官方文档里面去寻找。
- 参考文档:https://docs.python.org/zh-cn/3.11/library/stdtypes.html#list
P95 传参机制和分享 2024/10/2
一、list、tuple、set和dict传参机制
- 看一个案例,分析结果是什么?[列表]
# ----------------list--------------------------------
def f1(my_list):
print(f"2:f1() my_list: {my_list}地址是:{id(my_list)}")
my_list[0] = "jack"
print(F"3:f1() my_list: imy_list]地址是:{id(my_list)}")
# 测试
my_list = ["tom", "mary", "hsp"]
print(f"1:my_list: {my_list}地址是:{id(my_list)}")
# 调用函数
f1(my_list)
print(f"4:mly _五ist: {my_list}地址是:{id(my_list)}")
- 列表结论:在函数中修改列表中的值会改变原列表的值,输出的地址都是一样的。
- 元组-tuple
# tuple 元组
def f2(my_tuple):
print(f"②f2() my_tuple: {my_tuple}地址是: {id(my_tuple)}")
# 不能修改
# my_tuple[0] = "red "
print(f"③f2() my_tuple: {my_tuple}地址是:{id(my_tuple)}")
# 测试
my_tuple = ("hi", "ok", "hello")
print(f"①my_tuple: {my_tuple}地址是:{id(my_tuple)}")
f2(my_tuple)
print(f"④my_tuple: {my_tuple}地址是:{id(my_tuple)}")
- 集合set()是可变数据类型,执行机制和列表一致
def f3(my_set):
print(f"②f3() my Tset: {my_set}地址是: {id(my_set)}")
my_set.add("<<红楼梦>>")
print(f"③f3() my_set: {my_set}地址是:{id(my_set)}")
# 测试
my_set = {"水浒", "西游", "三国"}
print(f"①my_set: {my_set}地址是:{id(my_set)}")
f3(my_set)
print(f"④my_set: {my_set}地址是:{id(my_set)}")
- 字典dict()
def f4(my_dict):
print(f"②f4( ) my_dict: {my_dict}地址是:{id(my_dict)}")
my_dict['address'] = "兰若寺"
print(f"③f4() my_dict: {my_dict}地址是:{id(my_dict)}")
# 测试
my_dict = {"name": "小倩", "age": 18}
print(f"①my_dict: {my_dict}地址是:{id(my_dict)}")
f4(my_dict)
print(f"my_dict: {my_dict}地址是:{id(my_dict)}")
二、小结
-
python数据类型主要有
整数int/浮点数float/字符串str/布尔值bool/元组tuple/ 列表list/字典dict/集合set
,数据类型分为两个大类,一种是可变数据类型;一种是不可变数据类型。 -
可变数据类型和不可变数据类型
可变数据类型:当该数据类型的变量的值发生了变化,如果它的内存地址不变,那么这个数据类型就是可变数据类型
不可变数据类型:当该数据类型的变量的值发生了变化,如果它的内存地址改变了,那么这个数据类型就是不可变数据类型
- Python数据类型
不可变数据类型:
数值类型(int、float)、bool(布尔)、string(字符串)、tuple(元组)
可变数据类型:
list(列表)、set(集合)、dict(字典)
三、本章回顾
P96 冒泡排序 2024/10/2
一、基本介绍
-
排序是将多个数据,按照指定的顺序进行排列的过程
-
排序的分类:
排序算法有:
一、冒泡排序
二、选择排序
三、插入排序
四、希尔排序
六、快速排序
七、堆排序
- 介绍:
冒泡排序(Bubble Sorting〉的基本思想是:重复地走访需要排序的元素列表,依次比较两个相邻的元素,如果顺序(如从大到小或从小到大)错误就交换它们的位置。重复地进行直到没有相邻的元素需要交换,则元素列表排序完成。
在冒泡排序中,值最大(或最小)的元素会通过交换慢慢“浮”到元素列表的“顶端”。就像“冒泡”一样,所以被称为冒泡排序
- 冒泡排序法案例:
下面我们举一个具体的案例来说明冒泡法,
列表:[24,69,80,5,13]
有5个元素,使用冒泡排序法将其排成一个从小到大的有序列表
思路分析:
- Python中使用sort方法可以完成快速排序:
# 老韩说明,如果只是完成排序功能,我们可以直接使用ist的方法sort,如下
num_list = [24, 69, 80, 57, 13]
# .center可以调整输出宽度
print("排序前".center(32, "-"))
print(f"num_list: {num_list}")
# 使用sort方法完成排序
num_list.sort()
print("排序后".center(32, "-"))
print(f"num_list: {num_list}")
- 使用冒泡排序,自己完成排序,了解底层原理,深刻理解(以后遇到不同业务,需要定制排序,也能处理)
- 1、先把代码写死"先死后活"
num_list = [24, 69, 80, 57, 13, 11, 900,-10,9]
# .center可以调整输出宽度
print("排序前".center(32, "-"))
print(f"num_list: {num_list}")
# 使用冒泡排序,自己完成排序,了解底层原理,深刻理解(以后遇到不同业务,需要定制排序,也能处理)
# 定义函数:完成排序
def bubble_sort(my_lsit):
"""
功能:对传入的列表排序-顺序从小到大
:param my_lsit:传入的列表
:return:无
"""
"""
第一轮排序:把最大的数放到最后的位置
第1次比较:[24,69,80,57,13]
第2次比较:[24,69,80,57,13]
第3次比较:[24,69,57,80,13]
第4次比较:[24,69,57,13,80]
"""
# j变量控制比较的次数,同时可以作为比较元素的下标
for j in range(0, 4): # [0,1,2,3]
# 如果前面的元素大于后面的元素就交换
if my_lsit[j] > my_lsit[j + 1]:
my_lsit[j], my_lsit[j + 1] = my_lsit[j + 1], my_lsit[j]
print("第一轮排序后的结果my_lsit", my_lsit)
"""
第二轮排序:把第二大数放到倒数第二的位置
第1次比较:[24,69,57,13,80]
第2次比较:[24,57,69,13,80]
第3次比较:[24,57,13,69,80]
"""
# j变量控制比较的次数,同时可以作为比较元素的下标
for j in range(0, 3): # [0,1,2]
# 如果前面的元素大于后面的元素就交换
if my_lsit[j] > my_lsit[j + 1]:
my_lsit[j], my_lsit[j + 1] = my_lsit[j + 1], my_lsit[j]
print("第二轮排序后的结果my_lsit", my_lsit)
"""
第三轮排序:把第三大数放到倒数第三的位置
第1次比较:[24,57,13,69,80]
第2次比较:[24,13,57,69,80]
"""
# j变量控制比较的次数,同时可以作为比较元素的下标
for j in range(0, 2): # [0,1,2]
# 如果前面的元素大于后面的元素就交换
if my_lsit[j] > my_lsit[j + 1]:
my_lsit[j], my_lsit[j + 1] = my_lsit[j + 1], my_lsit[j]
print("第三轮排序后的结果my_lsit", my_lsit)
"""
第四轮排序:把第四大数放到倒数第四的位置
第1次比较:[13,24,57,69,80]
"""
# j变量控制比较的次数,同时可以作为比较元素的下标
for j in range(0, 1): # [0,1,2]
# 如果前面的元素大于后面的元素就交换
if my_lsit[j] > my_lsit[j + 1]:
my_lsit[j], my_lsit[j + 1] = my_lsit[j + 1], my_lsit[j]
print("第四轮排序后的结果my_lsit", my_lsit)
bubble_sort(num_list)
- 用两层for循环优化
num_list = [24, 69, 80, 57, 13, 11, 900,-10,9]
# .center可以调整输出宽度
print("排序前".center(32, "-"))
print(f"num_list: {num_list}")
def bubble_sort(my_lsit):
"""
功能:对传入的列表排序-顺序从小到大
:param my_lsit:传入的列表
:return:无
"""
"""
通过分析,我们发现每轮的比较逻辑是一样的
我们只需要考虑变化部分即可,使用外层for循环来解决
"""
for i in range(0,4):
for j in range(0, 4-i): # [0,1,2]
# 如果前面的元素大于后面的元素就交换
if my_lsit[j] > my_lsit[j + 1]:
my_lsit[j], my_lsit[j + 1] = my_lsit[j + 1], my_lsit[j]
print(f"第{i+1}轮排序后的结果my_lsit", my_lsit)
bubble_sort(num_list)
- “后活”,改变列表元素个数,使用len()控制
num_list = [24, 69, 80, 57, 13, 11, 900,-10,9]
# .center可以调整输出宽度
print("排序前".center(32, "-"))
print(f"num_list: {num_list}")
# 使用冒泡排序,自己完成排序,了解底层原理,深刻理解(以后遇到不同业务,需要定制排序,也能处理)
# 定义函数:完成排序
def bubble_sort(my_lsit):
"""
功能:对传入的列表排序-顺序从小到大
:param my_lsit:传入的列表
:return:无
"""
"""
通过分析,我们发现每轮的比较逻辑是一样的
我们只需要考虑变化部分即可,使用外层for循环来解决
"""
# i变量来控制多少轮排序len
for i in range(0, len(my_lsit) - 1):
for j in range(0, len(my_lsit) - 1 - i): # [0,1,2]
# 如果前面的元素大于后面的元素就交换
# 如果是从小到大是:>;从大到小 <
if my_lsit[j] > my_lsit[j + 1]:
my_lsit[j], my_lsit[j + 1] = my_lsit[j + 1], my_lsit[j]
print(f"第{i + 1}轮排序后的结果my_lsit", my_lsit)
bubble_sort(num_list)
print("排序后".center(32, "-"))
print(f"num_list: {num_list}")
P97 顺序查找 2024/10/3
一、基本介绍
二、顺序查找案例
- 有一个列表:[白眉鹰王、金毛狮王、紫衫龙王、青翼蝠王]
猜名字游戏:从键盘中任意输入一个名称,判断列表中是否包含此名称【顺序查找】
要求:如果找到了,就提示找到,并给出下标值
- 如果只是完成一个查找,使用
list.index
就可以完成
# 老韩说明,如果只是完成查找功能,我们可以直接使用ist的方法index,如下
names_list = ["白眉鹰王", "金毛狮王", "紫衫龙王", "青翼蝠王"]
find_name = "金毛狮王"
print(names_list.index("金毛狮王")) # 1
- 除了掌握系统提供的index(),程序员也应当掌握一些基本的查找方法(以后遇到不同业务,需要定制排序,也能处理)
names_list = ["白眉鹰王", "金毛狮王", "紫衫龙王", "青翼蝠王"]
def seq_search(my_list, find_val):
"""
功能:顺序查找指定的元素
:param my_list:传入的列表(即要查找的列表)
:param find_val:要查找的值/元素
:return:如果查找到就返回对应的索引下标,否则返回-1
"""
"""
思路分析:
1. 对列表进行遍历,如果找到了,则返回对应下标
2. 如果遍历结束,没有找到,则返回-1
"""
find_index = -1
# 遍历
for i in range(len(my_list)):
# 如果当前的元素就是查找的值就返回当前的索引
if my_list[i] == find_val:
print(f"恭喜找到对应的值{find_val}下标是{i}")
find_index = i
break # 退出for循环
else:
print(f"没有找到对应的值{find_val}")
return find_index
print(seq_search(names_list, "金毛狮王"))
- 思考题:
如果一个列表中有多个要查找的元素/值,比如前面的列表有两个金毛狮王,请思考,怎样才能把满足查询条件的元素的下标,都返回.
# 编写顺序查找函数seq_search
names_list = ["白眉鹰王", "金毛狮王", "紫衫龙王", "青翼蝠王","金毛狮王","金毛狮王"]
def seq_search2(my_list, find_val):
# 定义一个空列表
find_index = []
# 遍历
for i in range(len(my_list)):
# 如果当前的元素就是查找的值就保存到find_index
if my_list[i] == find_val:
# 将找到的下标,添加到find_index
find_index.append(i)
return find_index
res_index = seq_search2(names_list, "金毛狮王")
print(res_index)
P98 二分查找 2024/10/3
一、查找案例
- 二分查找案例:
请对一个列表(元素是从小到大排序的)进行二分查找
[1,8,10,89,1000,1234]
,输入一个数看看该列表是否存在此数,并且求出下标,如果没有就返回-1
- 思路分析:
# @Author :zjc
# @File :03_binary_search.py
# @Time :2024/10/3 17:36
"""
二分查找的思路分析
前提:该列表是一个排好序的列表(为了分析方便,就以从小到大的列表为例分析
1.找到列表的中间数 mid_val和find_val比较
2.如果mid_val > find_val ,则到 mid_val的左边查找
3.如果mid_val < find_val ,则到 mid_val的右边查找
4.如果mid_val = find_val ,则到找到,返回对应的下标即可
5.不断的重复1-4步骤,这里就是不断的折半,使用while
6.如果while 结束,都没有找到,说明ind_val 没有在列表
"""
# 查找的列表
num_list = [1, 8, 10, 89, 1000, 1234]
# 编写二分查找的函数
def binary_search(my_list, find_val):
"""
功能:完成二分查找
:param my_list: 要查找的列表(有顺序的)
:param find_val:要查找的元素/值
:return:返回对应的下标,如果没有找到返回-1
"""
left_index, right_index = 0, len(my_list) - 1
# 定义找到数的下标
find_index = -1
# 使用while循环不断的折半比较满足条件:left_index <= right_index
while left_index <= right_index:
# 中间数的下标/索引
mix_index = (left_index + right_index) // 2
# 1.如果mid_val > find_val ,则到 mid_val的左边查找
# 2.在左边查找就相当于移动到中间数的 索引-1
if my_list[mix_index] > find_val:
right_index = mix_index - 1
# 2.在右边查找就相当于移动到中间数的 索引+1
elif my_list[mix_index] < find_val:
left_index = mix_index + 1
else: # 相等
find_index = mix_index
break # 找到就退出while循环
return find_index
# 测试:
res_index = binary_search(num_list, 1)
if res_index == -1:
print("没有找到该数")
else:
print(f"找到数,对应的下标{res_index}")
二、二分查找的细节
-
二分查找的前提是该列表已经是一个排好序的列表(从小到大或者从大到小)
-
排列的顺序是从小到大还是从大到小,会影响二分查找的代码逻辑[举例说明]
-
把列表改成从大到小排序,看看是否还能正确盘找?又应当如何修改
# 将大小更换一下
if my_list[mix_index] < find_val:
# 同样的操作
elif my_list[mix_index] > find_val:
P99 本章作业 2024/10/4
一、练习
- 随机生成10个整数(1-100的范围)保存到列表,使用冒泡排序,对其进行从大到小排序
# @Author :zjc # @File :04_homework01.py # @Time :2024/10/4 18:50 import random my_list = [] for i in range(0, 10): my_list.append(random.randint(1, 100)) # my_list.sort() print("排序前:", my_list) def list_sort(my_list): for i in range(len(my_list) - 1): for j in range(len(my_list) - 1 - i): if my_list[j] < my_list[j + 1]: my_list[j], my_list[j + 1] = my_list[j + 1], my_list[j] list_sort(my_list) print("排序后:", my_list)
- 在第1题的基础上,使用二分查找,查找是否有8这个数,如果有,则返回对应的下标,如果没有,返回-1
老韩提示:注意这里要查找的列表是从大到小…def binary_search(my_list, find_val): left_index, right_index = 0, len(my_list) - 1 find_index = -1 while left_index <= right_index: mid_index = (left_index + right_index) // 2 if my_list[mid_index] < find_val: right_index = mid_index - 1 elif my_list[mid_index] > find_val: left_index = mid_index + 1 else: find_index = mid_index break return find_index res_index = binary_search(my_list, 99) if res_index == -1: print("没有找到!") else: print("查找数的索引是",res_index)