目录

第十章:高级数据结构

本章目标

完成本章学习后,你将能够:

collections模块

Counter计数器

from collections import Counter
 
# 创建计数器
c = Counter(['a', 'b', 'a', 'c', 'a', 'b'])
print(c)  # Counter({'a': 3, 'b': 2, 'c': 1})
 
# 从字符串创建
c = Counter("mississippi")
print(c)  # Counter({'i': 4, 's': 4, 'p': 2, 'm': 1})
 
# 常用方法
print(c.most_common(2))  # [('i', 4), ('s', 4)],最常见的2个
print(c.elements())      # 迭代所有元素
 
# 数学运算
c1 = Counter(a=3, b=1)
c2 = Counter(a=1, b=2)
print(c1 + c2)  # Counter({'a': 4, 'b': 3})
print(c1 - c2)  # Counter({'a': 2})

defaultdict默认字典

from collections import defaultdict
 
# 默认值为列表
words = ["apple", "bat", "bar", "atom", "book"]
by_first_letter = defaultdict(list)
 
for word in words:
    by_first_letter[word[0]].append(word)
 
print(dict(by_first_letter))
# {'a': ['apple', 'atom'], 'b': ['bat', 'bar', 'book']}
 
# 默认值为整数(计数)
counts = defaultdict(int)
for word in words:
    counts[word[0]] += 1

deque双端队列

from collections import deque
 
# 创建
d = deque([1, 2, 3, 4, 5])
 
# 两端操作(都是O(1))
d.append(6)        # 右端添加
d.appendleft(0)    # 左端添加
right = d.pop()    # 右端移除
left = d.popleft() # 左端移除
 
# 限制大小(滑动窗口)
d = deque(maxlen=3)
for i in range(10):
    d.append(i)
    print(list(d))  # 始终只保留最后3个元素
 
# 旋转
d = deque([1, 2, 3, 4, 5])
d.rotate(2)   # 向右旋转2位: [4, 5, 1, 2, 3]
d.rotate(-1)  # 向左旋转1位: [5, 1, 2, 3, 4]

堆和优先队列

import heapq
 
# 创建堆(列表)
heap = []
 
# 添加元素
heapq.heappush(heap, 3)
heapq.heappush(heap, 1)
heapq.heappush(heap, 4)
heapq.heappush(heap, 1)
 
# 弹出最小元素
print(heapq.heappop(heap))  # 1
 
# 从列表构建堆
data = [3, 1, 4, 1, 5, 9, 2, 6]
heapq.heapify(data)
 
# 获取n个最大/最小值
print(heapq.nlargest(3, data))  # [9, 6, 5]
print(heapq.nsmallest(3, data)) # [1, 1, 2]
 
# 优先队列应用
tasks = []
heapq.heappush(tasks, (2, "write code"))    # (优先级, 任务)
heapq.heappush(tasks, (1, "design"))
heapq.heappush(tasks, (3, "test"))
 
while tasks:
    priority, task = heapq.heappop(tasks)
    print(f"[{priority}] {task}")

链表实现

class Node:
    """链表节点"""
    def __init__(self, data):
        self.data = data
        self.next = None
 
class LinkedList:
    """单向链表"""
    def __init__(self):
        self.head = None
        self.size = 0
 
    def append(self, data):
        """在末尾添加"""
        new_node = Node(data)
        if not self.head:
            self.head = new_node
        else:
            current = self.head
            while current.next:
                current = current.next
            current.next = new_node
        self.size += 1
 
    def prepend(self, data):
        """在头部添加"""
        new_node = Node(data)
        new_node.next = self.head
        self.head = new_node
        self.size += 1
 
    def delete(self, data):
        """删除第一个匹配的节点"""
        if not self.head:
            return
 
        if self.head.data == data:
            self.head = self.head.next
            self.size -= 1
            return
 
        current = self.head
        while current.next:
            if current.next.data == data:
                current.next = current.next.next
                self.size -= 1
                return
            current = current.next
 
    def find(self, data):
        """查找节点"""
        current = self.head
        index = 0
        while current:
            if current.data == data:
                return index
            current = current.next
            index += 1
        return -1
 
    def to_list(self):
        """转换为Python列表"""
        result = []
        current = self.head
        while current:
            result.append(current.data)
            current = current.next
        return result
 
# 使用
ll = LinkedList()
ll.append(1)
ll.append(2)
ll.append(3)
ll.prepend(0)
print(ll.to_list())  # [0, 1, 2, 3]

本章练习

1. 使用Counter统计文本词频,输出前10 2. 使用deque实现滑动窗口最大值 3. 使用堆合并K个有序列表 4. 实现双向链表 5. 使用优先队列实现任务调度器

下一章:第十一章:函数基础