Python 数据结构

数据结构

常见的数据结构有 线性表 、 链表 、 散列表 、队列、栈、 树 (二叉树、平衡二叉树、红黑树、BTree树、 B+Tree树) 、 图 等 ~~~

  • 列表 list
  • 元组 tuple
  • 集合 set
  • 字典 dict

列表 list

列表是一个线性表、特点: 用来存储多个数据的容器 , 空间地址连续、存储的数据 是有序可重复 的。 线性表 可以 通过 索引index 进行数据的访问 、时间复杂度 O(1) , 添加数据 和 删除数据 效率较低 、时间复杂度为 O(n) n 代表列表的长度 。

列表中的索引 支持 正索引 和 负索引 、 同一个位置的数据 它的正索引 和 负索引 满足一个公式:

正索引 - 负索引 = 列表的长度 、列表长度可以使用 len 函数获取

列表 是 可变的 可迭代对象

列表的创建方式

  • 字面量定义方式

    python 复制代码
    # 创建 一个 空列表 
    ls = [] 
    
    # 创建一个 包含指定内容的列表 , 数据之间使用 逗号分隔
    ls = [1, 2, 3, 4, 5]
    
    # 创建一个包含 不同类型的数据 
    ls = [1, "hello", True, None, [1, 2, 3] ] 
    
    # 创建一个列表、存储一些 相同的数据 
    ls = [1, 2, 3, 1, 2 ,3]
    
    print(ls)
  • 使用 list 工厂函数构建

    python 复制代码
    # 使用 list 工厂函数构建一个空列表 
    ls = list()
    string = "hello" 
    # 将字符串转成 列表 
    ls = list(string)
    # 输出对应的列表数据 
    
    # list 工厂函数 可以将 任意的 可迭代对象 转成 列表 
    #   常见的可迭代对象有: 列表、 元组、 集合、 字典 、 字符串 、 range 对象
    ls = list(range(10, 100))
    
    print(ls)
  • 列表生成推导式

    列表生成推导式的语法:

    python 复制代码
    [ exp for var in iterable if condition ] 
    语法: 
    
    exp :  是一个表达式,是 最终 计算列表中数据 的表达式 
    
    var :  是一个变量、 代表 iterable 可迭代对象中的每一个元素
    
    iterable :  是一个可迭代对象
    
    condition :  是一个条件表达式,用来过滤保留满足条件的 var 

    该语法中 , for 结构 可以出现 1 ~ N 次 , if 结构 可选, 如果有、则必须出现在 所有的 for 结构的 后面 ~~~

    列表生成推导式的执行顺序是:

    先执行 所有的 for 循环 (多个 for 采用 嵌套循环的方式进行执行) 、

在 最后一个 for 循环的内部 执行 if 条件 , 当 if 条件成立的时候,

保留 exp 执行的结果 。

python 复制代码
# 快速生成一个列表
ls = [x + y for x in range(10) for y in range(10) if x == y]
# 输出列表中内容
print(ls)

列表的基本操作

  • 添加数据
    • append(x) : 将 数据追加到 列表的 尾部

    • insert(index, x) : 将 数据 x 添加到 指定索引 index 的前面 ,

      如果 index 超出了 正索引的 范围 ,则 添加到列表的尾部 ,

      如果 index 超出了 负索引的 范围, 则添加到 列表的头部

python 复制代码
ls = [] 

# 向列表中添加数据 
ls.append(10)

ls.append(20)

# 向 指定索引位置前 添加数据 
ls.insert(0, 5)

# 如果添加的索引值 超出了 正索引的范围 
ls.insert(10, 1000)

# 向索引为 -1 的位置前 添加一个元素 xyz 
ls.insert(-1, "xyz")

# 如果添加的索引值 超出了 负索引的范围 、则添加到头部
ls.insert(-100, "abc")
  • 修改数据

    python 复制代码
    ls[index] =  val

    index 的索引值 不能超出 列表的索引范围 、否则会产生 IndexError 错误!

  • 删除数据

    • pop(index) : 根据 索引 删除指定位置的元素、 如果 没有传入 index 值, 则默认删除 列表中的最后一个数据
    • remove(val) : 根据值删除 列表中满足条件的 第一个元素 ,如果元素不存在,则产生 ValueError 错误
  • 查看数据

    • lsindex : 获取指定索引位置的元素,索引如果超出范围,会产生错误~~~
    • ls.index(val) : 根据 指定的值 获取该值 在列表中 第一次出现的索引位置 ,如果不存在, 则产生 ValueError错误
    • ls.index(val, start, end) : 从指定区间 [start, end) 查找第一个 val 元素的索引位置,找不到抛出错误!

列表中常见的方法

  • clear() : 清空列表
  • copy() : 浅克隆/拷贝一个列表
  • count(val) : 获取 val 在列表中出现的个数
  • extend(iterable) : 将一个 可迭代对象中的数据 追加到 列表的尾部
  • reverse() : 将列表中的元素 进行反转
  • sort(key=fn, reverse=False) : 对列表中的元素 进行排序 , key 用来设置排序规则, reverse 用来反转 排序规则,默认按照 自然顺序

列表的遍历方式

  • 基于 索引的遍历方式

    python 复制代码
    ls = [32, 65 ,23 ,76 , 43]
    
    # 基于索引的遍历方式 
    for i in range(len(ls)):
        print(i, ls[i])
  • 基于 值的遍历方式

    python 复制代码
    for val in ls:
        print(val)
  • 基于 索引和 值的遍历方式

    python 复制代码
    for index, val in enumerate(ls):
        print(index, val)

列表支持的运算符

  • 列表支持 +* 运算

  • + : 两个列表支持 使用 加法运算 进行 数据合并 ~~

  • * : 一个列表 和一个整数 ( >=0 ) 支持 乘法运算 、将列表中的元素重复 多少次

  • 列表支持 关系运算符 >, >= , < , <= , == , !=

    两个列表 同位置的元素 进行比较、且 同位置的元素 类型必须 可以支持比较大小

  • 列表支持 成员运算符 in , not in

列表的切片技术

切片是用来 快速 提取 列表中 数据的 一种 手段 、

切片 主要通过 [start: end: step] 语法来实现的

start : 从 哪一个索引位置 开始进行剪切,

当 步长 > 0 的时候, start 默认值是 0, 当步长 <0 , 默认值是 -1

end : 在 哪一个索引位置 结束剪切 (不包含结束索引位置)

当 步长 > 0 的时候, end 的默认值是 列表的长度、当步长 < 0, 默认值是 -length - 1

step : 默认值 是1, 代表 每次 剪切数据的步长

0 : 从左 向右 进行 剪切

< 0 : 从 右 向左 进行 剪切

  • 提取数据

    python 复制代码
    ls = [1, 34, 65, 23, 76, 23, 87, 3, 87]
    # 克隆列表
    print(ls[:])
    # 剪切列表中的最后2个数据
    print(ls[-2:])
    # 从列表起始索引位置剪切到 列表最后一位、且不包含最后一个数据
    print(ls[:-1])
    # 去掉列表 前面 2个数据 和 后面 1个数据
    print(ls[2:-2])
    # 从 右向左剪切,没有区间 所以返回 空列表
    print(ls[2:-2:-1])
    # 从右向左剪切,去掉 最后一个数据 和 前三个数据
    print(ls[-2:2:-2])
    # 将列表中的元素 进行反转
    print(ls[::-1])
  • 修改数据

    当切片进行数据修改的时候、步长为1的时候,那么修改提供的值的个数 可以任意 , 如果 步长不为 1, 那么 修改的数据个数 必须和 切片提取到的数据个数 保持完全一致 ~~~

  • 删除数据

    python 复制代码
    ls = [23, 65, 12, 65, 23, 76, 43 ,78]
    
    del ls[2:-2:2]

列表排序

了解常见的排序算法 、冒泡排序、选择排序 、插入排序、 、快排 、堆排序、 桶排序、 归并排序 等 。。。。

不太正规的排序算法(好玩的排序算法): 随机排序 、睡眠排序

  • 冒泡排序

每两个相邻的数 进行 比较 、如果大值在前、小值在后、则进行交换~, 每一轮比较 可以实现 将列表中的最大值 沉到 尾部 ~~~~

冒泡排序的时间复杂度是 O(n^2)

python 复制代码
ls = [32, 65, 12, 65, 12, 67, 1, 34, 87]

# 获取列表长度 
length = len(ls)

# 外层循环 负责控制 需要比较多少 轮
for x in range(0, length - 1):
    # 内层循环 负责 两个相邻的数字 进行比较 
    for y in range(length - x - 1):

        # 获取 2个相邻的数字 
        if ls[y] > ls[y + 1]:
            # 交换
            ls[y], ls[y+1] = ls[y+1], ls[y] 

# 整个循环结束后、输出已排序后的列表
print(ls)
  • 选择排序

将 列表中的 一个元素 和 它 后面的所有元素 进行比较,如果大值在前,小值在后,进行交换,每一轮可以将列表中最小值沉到列表头部

选择排序的时间复杂度是 O(n^2)

python 复制代码
ls = [10, 6, 32, 76, 43, 7, 12]  

# 获取长度
length = len(ls)

# 编写一个循环 、用来控制要比较的数字 
for x in range(0, length - 1):
    # 编写一个循环、用来获取 当前 x 位置后的所有数据 
    for y in range(x+1, length):
        # 比较 这个数 和它后面的数大小         
        if ls[x] > ls[y]:
            # 交换
            ls[x], ls[y] = ls[y], ls[x]

# 整个循环结束后、输出已排序后的列表
print(ls)
  • 插入排序

将列表中的一个元素 插入 到 以一个已经排序好的列表中

插入排序算法 是对 选择排序的 优化, 时间复杂度是 O(n) ~ O(n^2)

二维列表

如果一个列表 、它的所有元素 仍旧是 列表、那么这个列表 被称为 二维列表 。

元组 tuple

是用来进行多个数据存储的容器、用法上 和 列表非常相似 ~

元组 和 列表的区别

  1. 元组是不可变的、 列表是可变的
  2. 元组 使用 小括号 () 进行标记 、列表 使用 中括号 \[\] 进行标记
  3. 元组性能 比 列表更高 、内存占用更小

元组的创建方式

  • 字面量定义方式

    a) 元组中 有且只有 1个数据的时候, 这个数据的后面 必须添加 逗号

    b) 当创建一个 非空元组的时候,小括号可以省略不写 !!!(不推荐)

c) 元组中的元素类型 支持 存储 可变类型 、但不推荐~~~

python 复制代码
 # 创建一个 空的元组, 
tp = () 

tp2 = ()
# 输出 2个元组的内容是否相同 
print(tp == tp2)

# 比较 2个元组的地址是否相等 
print(tp is tp2)

# 创建一个长度 为 1的元组 
tp3 = 100, 

tp4 = (100, )

print(tp3 is tp4)

# 创建一个 长度 > 1 的元组 
tp5 = (1, 2, 3, 4, 5)

print(tp5, type(tp5))


tp6 = ([1, 2, 3], [4, 5, 6])

tp7 = ([1, 2, 3], [4, 5, 6])

print(tp6 is tp7)

# 元组中 只有存储的有可变类型,地址则不同
ls1 = [1, 2, 3]
ls2 = [4, 5, 6]

tp8 = (ls1, ls2)
tp9 = (ls1, ls2)

print(tp8 is tp9)
  • tuple 工厂函数 进行创建 tuple 函数 可以将任意的 可迭代对象 转成 元组

元组的基本操作

  • 使用 [index] 语法 可以获取数据
  • index(val) : 根据值找满足条件的一个元素的索引,如果找不到 ,则产生 ValueError 错误
  • index(val, start, end) : 从指定区间 [start, end) 查找第一个 val 元素的索引位置,找不到抛出错误!
  • count(val) : 统计 val 在元组中出现的次数

元组的遍历方式

  • 基于索引的遍历方式
  • 基于值得遍历方式
  • 基于 索引和值的遍历方式

元组支持的运算符

  • 算术运算符: 具体用法参考列表
  • 关系运算符 : >, >= , < , <= , == , !=
  • 成员运算符: in , not in

元组切片

  • 提取数据

集合 set

集合是一个用来存储多个数据的容器、底层采用 散列表 + 链表的数据结构 实现的 ~ 、集合存储的数据是 无序不可重复

散列表 : 也叫 哈希表 、是一种 基于 hash 算法 进行数据存储的 表 , 在 python 语言中 可以通过 hash 函数 获取 某个数据的 hash值

集合中 存储的数据 必须是 可哈希 (能够使用hash算法进行计算) 的

hash 算法的特点是: 相同内容的 hash值一定相同, 内容不同 hash 值 尽可能地不同 ~~

可变 类型 不可做 hash 运算 ~~~

集合中存储的数据是 不可变的、 集合是可变的。

集合去重的原理

存储一个新的数据的时候,会先 获取该数据的 hash值、再将 hash值 和 散列表的 长度 - 1 做 位与运算,得到该数据要存储的索引位置

根据索引位置 判断 该位置 是否已有数据 、 如果 没有数据、 则直接将数据 存入(链表)即可 , 如果该位置有数据、则 遍历该位置的链表组成的数据 , 判断 链表中 每一个数据的 hash 值是否 和 插入数据的 hash 值一致, 如果没有一致的, 则插入到 链表的尾部

如果 找到 hash 相同的值 , 则 比较 2个值的 内容 是否相等, 如果不相同, 插入到链表尾部, 否则 什么都不做

当 hash 值相同 、且 内容相同 则 去重

集合的创建方式

  • 字面量定义方式

  • set 工厂函数创建

  • 集合生成推导式

    python 复制代码
    # 创建一个 包含指定数据的集合 
    set1 = {1, 2, 3, 4, 5, 1, 2, 3}
    
    # 不能存储 可变类型, 可变类型不可hash
    # set1 = { [1, 2, 3],  1, 2, 3 }
    # set1 = {  {1, 2, 3},  {4, 5, 6} }
    # 创建一个 空的集合 , 空集合 只能使用 set() 来构建
    set1 = set() 
    
    # set 工厂函数 可以将 任意 可迭代对象 转成 集合 
    string = "hello3" 
    
    set1 = set(string)
    
    print(set1, type(set1))
    
    # 使用 集合生成推导式 快速构建集合 
    set1 = { x for x in range(1, 10)}
    
    print(set1)

集合的基本操作

  • add(x) : 添加数据

    python 复制代码
    set1 = set() 
    
    # 向集合中添加一个元素 
    set1.add(10)
    set1.add("xyz")
    set1.add("hello")
    set1.add(True)
    # 添加一个重复数据、会被自动去掉
    set1.add(True)
    
    print(set1)
  • pop() : 随机从集合中删除一个元素

  • remove(val) : 删除集合中 指定的元素、如果该元素 不存在,则 抛出 KeyError 错误

  • discard(val) : 删除集合中 指定的元素、 无论元素是否存在,都不会报错

集合中常见的方法

  • clear() : 清空集合
  • union(set) : 计算 2个集合的并集 、并返回新的集合
  • update(set) : 计算 2个集合的并集 、将结果 存储到第一个集合中
  • intersection(set) : 计算 2个集合的交集 、并返回新的集合
  • intersection_update(set) : 计算 2个集合的交集 、将结果 存储到第一个集合中
  • difference(set) : 计算 2个集合的差集 、并返回新的集合
  • difference_update(set) : 计算 2个集合的差集 、将结果 存储到第一个集合中
  • symmetric_difference(set) : 计算 2个集合的补集 、并返回新的集合
  • symmetric_difference_update(set) : 计算 2个集合的补集 、将结果 存储到第一个集合中
  • issubset(set) : 判断 set 是否是 指定集合的 子集
  • issuperset(set) : 判断 set 是否是 指定集合的 超集

集合常见的运算符

  • 算术运算符 : - : 两个集合 可以使用 减号 做 差集运算
  • 位运算符 : & (交集) 、 | (并集) 、 ^ (补集)
  • 成员运算符: in , not in
  • 关系运算符 : == (比较 2个集合是否相等) 、 != 、 > , >= (超集) , < (真子集) , <= (子集)

字典 dict

字典是用来 存储 键值对结构的数据容器 、每一个数据 都包含 键和值, 键和值之间使用 : 分割、多个数据之间使用 , 分割。

字典中的键 是 无序且 不可重复的 、键的类型 不能是 可变类型 。值的类型 没有限制

是可变数据类型

字典的创建方式

  • 使用字面量的方式定义

    python 复制代码
    # 创建一个空的字典
    dct = {} 
    
    # 创建一个带有内容的字典 
    dct = {"name": "张三" , "age": 20, }
  • 使用 dict 工厂函数定义

    python 复制代码
    # 创建一个空的字典
    dct = dict()  
    
    # 将一个形似字典的可迭代对象(可迭代对象中的每一个数据 也是一个可迭代对象,且长度为 2 ) 转成字典 
    
    mapping = [ ("name", "张三") , ("age",  20) , ("gender",  "男")]
    dct = dict(mapping)
    
    # 将 关键字参数转换成字典 
    dct = dict(a=1, b=2, c=3, abc=4)
  • 字典生成推导式

    python 复制代码
    ls = [1, 2, 3, 4, 5]
    
    dct = { x:None for x in ls}
    
    dct =  { index:x for index, x in enumerate(ls) }

字典的基本操作

  • 添加数据

    python 复制代码
    dct = {}
    
    # 键如果不存在,则添加数据、否则 修改数据
    dct["name"] = "张三"
    
    # 向字典中 添加一个键值对数据、如果键不存在,则添加, 否则 什么都不做 ~~~
    dct.setdefault("name",  "李四")
  • 修改数据

    python 复制代码
    # 键如果不存在,则添加数据、否则 修改数据
    dct["name"] = "张三"
  • 删除数据

    python 复制代码
    #  根据 键删除、并返回对应的值、 如果键不存在,则抛出 KeyError错误
    dct.pop("name")
    
    # 根据 键删除、并返回对应的值、 如果键不存在,则返回 默认值
    dct.pop("name",  None)
    
    del dct["name"]
  • 获取数据

    python 复制代码
    # 根据键获取值、如果 键不存在,则抛出 KeyError 错误
    name  = dct["name"]
    
    # 根据键获取值、如果 键不存在 , 则返回 None 
    name = dct.get("name")
    
    # 根据键获取值、如果 键不存在 , 则返回 张三 
    name = dct.get("name", "张三")

字典中常见的方法

  • copy() : 浅克隆一个新字典
  • clear() : 清空字典
  • update(dict) : 合并 2个字典
  • items() : 获取 所有键值对组成的 可迭代对象 ,格式 ("name" , "张三"), ("age" , 20)
  • keys() : 获取 字典中所有 键 组成的 可迭代对象, 格式 "name" , "age"
  • values() : 获取 字典中 所有 值组成的可迭代对象

字典的遍历方式

  • 键遍历

    python 复制代码
    dct = {"name": "张三", "age": 20, "gender": "男"} 
    
    # 键遍历 
    for key in dct:
        print(key, dct.get(key))
  • 值遍历

    python 复制代码
    dct = {"name": "张三", "age": 20, "gender": "男"} 
    
    # 值遍历
    for val in dct.values():
        print(val)
  • 键值对遍历

    python 复制代码
    dct = {"name": "张三", "age": 20, "gender": "男"} 
    
    # 键值对遍历 
    for key, val in dct.items():
        print(key, val)

字典支持的运算符

  • 位运算符: | 合并 2个字典 、并返回一个合并后的新字典
  • 成员运算符 : in , not in : 判断 字典中的键是否存在
  • 关系运算符 : 只 支持 ==!= 两个运算
相关推荐
LadenKiller1 小时前
2026年量化工具增量,放回回测模拟实盘阶段判断
人工智能·python
石一峰6991 小时前
驱动:私有数据为什么要在三个地方各挂一遍?
数据库·python·算法
2601_956319881 小时前
最新量化软件怎么选,先按能力短板匹配工具类型
人工智能·python
Tbisnic1 小时前
26.AI大模型:RNN、LSTM、GRU
人工智能·python·rnn·gru·大模型·llm·lstm
七夜zippoe2 小时前
OpenClaw 实战:智能文档助手——从问答到生成的完整方案
人工智能·python·机器学习·openclaw·智能文档
卡提西亚3 小时前
leetcode-179. 最大数
python·算法
ECT-OS-JiuHuaShan3 小时前
严格证明:还原论是ASCII,整体论是UTF-8的历史意义和价值
开发语言·人工智能·算法·量子计算
AC赳赳老秦3 小时前
时间开销自动统计:OpenClaw 记录工作任务时长、分析时间分配、给出优化建议
java·大数据·开发语言·python·自动化·deepseek·openclaw
Frostnova丶3 小时前
(17)LeetCode 41. 缺失的第一个正数
数据结构·算法·leetcode