(10)100天python从入门到拿捏《Python中的数据结构与自定义数据结构》

文章目录

Python 中的数据结构

一、Python 数据结构总览

Python 内置了丰富的数据结构,可以分为以下几类

类型 名称 是否可变 典型用途
**序列类型 ** list(列表) ✅ 可变 存储有序数据集合
tuple(元组) ❌ 不可变 存储固定的有序数据集合
str(字符串) ❌ 不可变 存储文本数据
range(区间) ❌ 不可变 用于生成整数序列
**集合类型 ** set(集合) ✅ 可变 存储无序、不重复元素
frozenset(冻结集合) ❌ 不可变 不可修改的集合
映射类型 dict(字典) ✅ 可变 键值对映射结构
其他容器类型 dequeCounterdefaultdictOrderedDictnamedtuple (在 collections 模块中) 不同 特殊功能的数据结构

二、序列类型

序列是 Python 最基本、最常用的数据结构。特点是 有序、可索引、可切片

1. List

定义:[] 定义的有序可变序列。

复制代码
fruits = ["apple", "banana", "cherry"]

常用操作:

操作 示例 说明
访问元素 fruits[0] 索引访问(从 0 开始)
切片 fruits[1:3] 获取子列表
修改 fruits[1] = "pear" 修改元素
添加 fruits.append("grape") 在末尾添加
插入 fruits.insert(1, "orange") 在指定位置插入
删除 fruits.remove("apple") / del fruits[0] 按值/索引删除
排序 fruits.sort() 原地排序
反转 fruits.reverse() 原地反转
统计 len(fruits) 元素个数

特点:

  • 可变(可以添加、删除、修改元素)
  • 元素可以是不同类型(如 [1, "abc", 3.14, [1,2]]

2. Tuple

定义:() 定义的有序、不可变序列。

py 复制代码
point = (10, 20)

操作与列表类似,但不可修改:

py 复制代码
print(point[0])     # ✅ 可以访问
# point[0] = 100     # ❌ 报错,不可修改

特点:

  • 不可变,可用于字典键或集合元素;
  • 适合存储固定结构的数据(如坐标、RGB 值等);
  • 支持 解包(unpacking)
py 复制代码
x, y = point  # x=10, y=20

3. String

定义:''""''' ''' 定义的不可变字符序列。

py 复制代码
text = "Hello Python"

常用操作:

py 复制代码
text.upper()          # 'HELLO PYTHON'
text.lower()          # 'hello python'
text.split()          # ['Hello', 'Python']
"-".join(["A","B"])   # 'A-B'
text.replace("Python", "World")  # 'Hello World'

特点:

  • 不可变;
  • 支持切片、拼接;
  • 丰富的字符串方法。

4. Range

用于生成一个整数序列,常用于循环。

py 复制代码
range(5)        # 0,1,2,3,4
range(2,10,2)   # 2,4,6,8

for 配合使用:

py 复制代码
for i in range(3):
    print(i)   # 输出 0,1,2

三、集合类型

集合是 无序、元素唯一 的容器。

1. Set

定义:

py 复制代码
nums = {1, 2, 3, 3, 2}
print(nums)  # {1, 2, 3}

常用操作:

操作 示例 说明
添加元素 nums.add(4)
删除元素 nums.remove(3) 若不存在则报错
且(交集) a & b
或(并集) `a b`
差集 a - b
对称差 a ^ b

特点:

  • 无序(不能索引);
  • 元素唯一;
  • 适合用于 去重集合运算

2. Frozenset

不可变集合,用法与 set 类似,但不能修改:

py 复制代码
a = frozenset([1,2,3])

可作为字典的键或集合的元素。


四、映射类型

1. Dict

定义: 键值对结构 {key: value}

py 复制代码
person = {"name": "Alice", "age": 25, "city": "Beijing"}

常用操作:

操作 示例 说明
访问 person["name"] 获取值
修改 person["age"] = 30 修改
新增 person["gender"] = "F" 新键值对
删除 del person["city"] 删除键值对
遍历键 for k in person: 遍历 key
遍历值 for v in person.values(): 遍历 value
遍历项 for k,v in person.items(): 遍历 (key,value)
查询 "name" in person 判断键是否存在

特点:

  • 键必须唯一、且必须是不可变类型
  • 值可以是任意类型;
  • 是 Python 最常用的"关联数组"结构。

五、collections 模块中的高级数据结构

Python 的 collections 模块提供了一系列增强型容器

类型 说明 示例
deque 双端队列,支持高效插入删除 适合队列或栈结构
Counter 计数器,用于统计元素出现次数 适合频率分析
defaultdict 带默认值的字典 避免 KeyError
OrderedDict 记住插入顺序(Python3.7+ 字典本身也已支持) 兼容旧代码
namedtuple 命名元组,可通过属性访问 可读性更高
ChainMap 多字典组合视图 合并配置时常用

案例:Counter

py 复制代码
from collections import Counter
text = "banana"
count = Counter(text)
print(count)  # Counter({'a': 3, 'n': 2, 'b': 1})

案例:deque

py 复制代码
from collections import deque
q = deque([1, 2, 3])
q.appendleft(0)
q.pop()
print(q)  # deque([0, 1, 2])

六、自定义数据结构(面向对象)

1. Stack

py 复制代码
# 1. 栈实现
class Stack:
    """栈 - 后进先出(LIFO)数据结构"""
    
    def __init__(self):
        self.items = []
    
    def push(self, item):
        """入栈操作"""
        self.items.append(item)
    
    def pop(self):
        """出栈操作"""
        if not self.is_empty():
            return self.items.pop()
        raise IndexError("栈为空,无法执行出栈操作")
    
    def peek(self):
        """查看栈顶元素"""
        if not self.is_empty():
            return self.items[-1]
        raise IndexError("栈为空,无法查看栈顶元素")
    
    def is_empty(self):
        """判断栈是否为空"""
        return len(self.items) == 0
    
    def size(self):
        """返回栈的大小"""
        return len(self.items)
    
    def __str__(self):
        return f"Stack({self.items})"

2. Queue

py 复制代码
# 2. 队列实现
class Queue:
    """队列 - 先进先出(FIFO)数据结构"""
    
    def __init__(self):
        self.items = []
    
    def enqueue(self, item):
        """入队操作"""
        self.items.append(item)
    
    def dequeue(self):
        """出队操作"""
        if not self.is_empty():
            return self.items.pop(0)
        raise IndexError("队列为空,无法执行出队操作")
    
    def front(self):
        """查看队首元素"""
        if not self.is_empty():
            return self.items[0]
        raise IndexError("队列为空,无法查看队首元素")
    
    def is_empty(self):
        """判断队列是否为空"""
        return len(self.items) == 0
    
    def size(self):
        """返回队列的大小"""
        return len(self.items)
    
    def __str__(self):
        return f"Queue({self.items})"

3. 链表

py 复制代码
class Node:
    """链表、树、图等数据结构的基础节点类"""
    def __init__(self, data=None):
        self.data = data
        self.next = None  # 用于链表
        self.left = None  # 用于树
        self.right = None  # 用于树
        self.neighbors = []  # 用于图
# 3. 链表实现
class LinkedList:
    """单向链表实现"""
    
    def __init__(self):
        self.head = None
        self.length = 0
    
    def append(self, data):
        """在链表末尾添加元素"""
        new_node = Node(data)
        if self.head is None:
            self.head = new_node
        else:
            current = self.head
            while current.next:
                current = current.next
            current.next = new_node
        self.length += 1
    
    def prepend(self, data):
        """在链表头部添加元素"""
        new_node = Node(data)
        new_node.next = self.head
        self.head = new_node
        self.length += 1
    
    def delete(self, data):
        """删除链表中第一个匹配的元素"""
        if self.head is None:
            return
        
        if self.head.data == data:
            self.head = self.head.next
            self.length -= 1
            return
        
        current = self.head
        while current.next:
            if current.next.data == data:
                current.next = current.next.next
                self.length -= 1
                return
            current = current.next
    
    def search(self, data):
        """在链表中查找元素"""
        current = self.head
        while current:
            if current.data == data:
                return True
            current = current.next
        return False
    
    def is_empty(self):
        """判断链表是否为空"""
        return self.head is None
    
    def size(self):
        """返回链表的大小"""
        return self.length
    
    def __str__(self):
        elements = []
        current = self.head
        while current:
            elements.append(str(current.data))
            current = current.next
        return " -> ".join(elements) if elements else "空链表"

4. 二叉树

py 复制代码
# 4. 二叉树实现
class BinaryTree:
    """二叉树实现"""
    
    def __init__(self, root_data=None):
        self.root = Node(root_data) if root_data is not None else None
    
    def insert(self, data):
        """插入元素到二叉树"""
        if self.root is None:
            self.root = Node(data)
        else:
            self._insert_recursive(self.root, data)
    
    def _insert_recursive(self, node, data):
        """递归插入辅助函数"""
        if data < node.data:
            if node.left is None:
                node.left = Node(data)
            else:
                self._insert_recursive(node.left, data)
        else:
            if node.right is None:
                node.right = Node(data)
            else:
                self._insert_recursive(node.right, data)
    
    def search(self, data):
        """在二叉树中查找元素"""
        return self._search_recursive(self.root, data)
    
    def _search_recursive(self, node, data):
        """递归查找辅助函数"""
        if node is None or node.data == data:
            return node is not None
        if data < node.data:
            return self._search_recursive(node.left, data)
        return self._search_recursive(node.right, data)
    
    def inorder_traversal(self):
        """中序遍历"""
        result = []
        self._inorder_recursive(self.root, result)
        return result
    
    def _inorder_recursive(self, node, result):
        """中序遍历辅助函数"""
        if node:
            self._inorder_recursive(node.left, result)
            result.append(node.data)
            self._inorder_recursive(node.right, result)
    
    def preorder_traversal(self):
        """前序遍历"""
        result = []
        self._preorder_recursive(self.root, result)
        return result
    
    def _preorder_recursive(self, node, result):
        """前序遍历辅助函数"""
        if node:
            result.append(node.data)
            self._preorder_recursive(node.left, result)
            self._preorder_recursive(node.right, result)
    
    def postorder_traversal(self):
        """后序遍历"""
        result = []
        self._postorder_recursive(self.root, result)
        return result
    
    def _postorder_recursive(self, node, result):
        """后序遍历辅助函数"""
        if node:
            self._postorder_recursive(node.left, result)
            self._postorder_recursive(node.right, result)
            result.append(node.data)
    
    def __str__(self):
        return f"二叉树中序遍历: {self.inorder_traversal()}"

5. 图

py 复制代码
# 5. 图实现
class Graph:
    """图实现 - 使用邻接表"""
    
    def __init__(self):
        self.vertices = {}
    
    def add_vertex(self, vertex):
        """添加顶点"""
        if vertex not in self.vertices:
            self.vertices[vertex] = []
    
    def add_edge(self, vertex1, vertex2, directed=False):
        """添加边,默认为无向图"""
        if vertex1 not in self.vertices:
            self.add_vertex(vertex1)
        if vertex2 not in self.vertices:
            self.add_vertex(vertex2)
        
        self.vertices[vertex1].append(vertex2)
        if not directed:
            self.vertices[vertex2].append(vertex1)
    
    def remove_vertex(self, vertex):
        """删除顶点"""
        if vertex in self.vertices:
            # 删除该顶点的邻接表
            del self.vertices[vertex]
            # 从其他顶点的邻接表中删除对该顶点的引用
            for v in self.vertices:
                if vertex in self.vertices[v]:
                    self.vertices[v].remove(vertex)
    
    def remove_edge(self, vertex1, vertex2, directed=False):
        """删除边"""
        if vertex1 in self.vertices and vertex2 in self.vertices[vertex1]:
            self.vertices[vertex1].remove(vertex2)
            if not directed and vertex1 in self.vertices[vertex2]:
                self.vertices[vertex2].remove(vertex1)
    
    def get_vertices(self):
        """获取所有顶点"""
        return list(self.vertices.keys())
    
    def get_edges(self):
        """获取所有边"""
        edges = []
        for vertex in self.vertices:
            for neighbor in self.vertices[vertex]:
                edges.append((vertex, neighbor))
        return edges
    
    def dfs(self, start_vertex):
        """深度优先搜索"""
        visited = set()
        result = []
        self._dfs_recursive(start_vertex, visited, result)
        return result
    
    def _dfs_recursive(self, vertex, visited, result):
        """DFS递归辅助函数"""
        visited.add(vertex)
        result.append(vertex)
        for neighbor in self.vertices[vertex]:
            if neighbor not in visited:
                self._dfs_recursive(neighbor, visited, result)
    
    def bfs(self, start_vertex):
        """广度优先搜索"""
        visited = set()
        queue = Queue()
        result = []
        
        visited.add(start_vertex)
        queue.enqueue(start_vertex)
        
        while not queue.is_empty():
            vertex = queue.dequeue()
            result.append(vertex)
            
            for neighbor in self.vertices[vertex]:
                if neighbor not in visited:
                    visited.add(neighbor)
                    queue.enqueue(neighbor)
        
        return result
    
    def __str__(self):
        result = "图结构:\n"
        for vertex in self.vertices:
            result += f"{vertex}: {self.vertices[vertex]}\n"
        return result

测试代码

py 复制代码
if __name__ == "__main__":
    # 测试栈
    print("\n1. 栈测试:")
    stack = Stack()
    stack.push(1)
    stack.push(2)
    stack.push(3)
    print(f"栈内容: {stack}")
    print(f"栈顶元素: {stack.peek()}")
    print(f"出栈: {stack.pop()}")
    print(f"出栈后栈内容: {stack}")
    
    # 测试队列
    print("\n2. 队列测试:")
    queue = Queue()
    queue.enqueue(1)
    queue.enqueue(2)
    queue.enqueue(3)
    print(f"队列内容: {queue}")
    print(f"队首元素: {queue.front()}")
    print(f"出队: {queue.dequeue()}")
    print(f"出队后队列内容: {queue}")
    
    # 测试链表
    print("\n3. 链表测试:")
    linked_list = LinkedList()
    linked_list.append(1)
    linked_list.append(2)
    linked_list.append(3)
    linked_list.prepend(0)
    print(f"链表内容: {linked_list}")
    print(f"查找元素2: {linked_list.search(2)}")
    linked_list.delete(2)
    print(f"删除元素2后: {linked_list}")
    
    # 测试二叉树
    print("\n4. 二叉树测试:")
    tree = BinaryTree()
    tree.insert(5)
    tree.insert(3)
    tree.insert(7)
    tree.insert(2)
    tree.insert(4)
    tree.insert(6)
    tree.insert(8)
    print(f"二叉树: {tree}")
    print(f"前序遍历: {tree.preorder_traversal()}")
    print(f"中序遍历: {tree.inorder_traversal()}")
    print(f"后序遍历: {tree.postorder_traversal()}")
    print(f"查找元素4: {tree.search(4)}")
    print(f"查找元素9: {tree.search(9)}")
    
    # 测试图
    print("\n5. 图测试:")
    graph = Graph()
    graph.add_vertex('A')
    graph.add_vertex('B')
    graph.add_vertex('C')
    graph.add_vertex('D')
    graph.add_edge('A', 'B')
    graph.add_edge('A', 'C')
    graph.add_edge('B', 'D')
    graph.add_edge('C', 'D')
    print(graph)
    print(f"所有顶点: {graph.get_vertices()}")
    print(f"所有边: {graph.get_edges()}")
    print(f"从A开始的DFS: {graph.dfs('A')}")
    print(f"从A开始的BFS: {graph.bfs('A')}")

七、总结对比表

类型 有序性 可变性 是否允许重复 常见用途
list 一般数据集合
tuple 不可变集合
str 文本数据
set 去重与集合运算
dict 键唯一 键值映射
frozenset 不可变集合
deque 队列/栈
Counter 计数统计

python学习专栏导航
(1)100天python从入门到拿捏《Python 3简介》
(2)100天python从入门到拿捏《python应用前景》
(3)100天python从入门到拿捏《数据类型》
(4)100天python从入门到拿捏《运算符》
(5)100天python从入门到拿捏《流程控制语句》
(6)100天python从入门到拿捏《推导式》
(7)100天python从入门到拿捏《迭代器和生成器》
(8)100天python从入门到拿捏《函数和匿名函数》
(9)100天python从入门到拿捏《装饰器》

相关推荐
寂静山林25 分钟前
UVa 11853 Paintball
算法
梨轻巧27 分钟前
pyside6安装:下载python、配置环境变量、vscode安装和测试pyside6、可能遇到的错误、pycharm 安装pyside6
python
wu_jing_sheng039 分钟前
电商销售数据分析实战:从数据挖掘到业务增长
python
第七序章43 分钟前
【C + +】C++11 (下) | 类新功能 + STL 变化 + 包装器全解析
c语言·数据结构·c++·人工智能·哈希算法·1024程序员节
voice67043 分钟前
西电现代密码学实验一
开发语言·python·密码学
FriendshipT43 分钟前
图像生成:PyTorch从零开始实现一个简单的扩散模型
人工智能·pytorch·python
Theodore_10221 小时前
深度学习(10)模型评估、训练与选择
人工智能·深度学习·算法·机器学习·计算机视觉
五条凪1 小时前
Verilog-Eval-v1基准测试集搭建指南
开发语言·人工智能·算法·语言模型
初学小白...1 小时前
反射概述and获得反射对象
开发语言·python
是店小二呀1 小时前
从“算法思维”到“算子思维”:我在昇腾AI开发中的认知跃迁
人工智能·算法