全部版块 我的主页
论坛 数据科学与人工智能 数据分析与数据科学 python论坛
247 0
2025-11-25

为了便于初学者更好地理解编程概念,我最近为俱乐部成员准备了一场培训,并为此编写了一些示例代码。这些代码不仅结构清晰,而且配有详尽的注释,帮助大家快速掌握核心要点。

在编写过程中,我还融入了一些个人在实践中积累的独特思路和技巧,旨在从不同角度启发学习者。相信通过阅读和实践这些内容,大家能够获得实质性的提升与启发。

# -*- coding : utf-8 -*-
"""
@author: 江南大学 —— 2025数据赋能俱乐部
@Description: 一个轻量、清晰且易扩展的Python双向链表实现
@Date: 2025-11-24 0:20
"""

# 双链表的节点类。下文用a、b、c表示节点,是为了增强大家对节点顺序的感知,不易出错
class Node:  # 只需要记忆前三个函数
    def __init__(self, val=None):  # 默认val为空
        self.val = val
        self.pre = None   # 初始为空
        self.next = None  # 初始为空

    # 在当前节点的下一个位置插入 b 节点
    def insert_next(self, b):
        a, c = self, self.next  # 先得到被新增节点的前、后节点,问题转化为在a、c之间插入b
        b.pre, b.next = a, c    # 先连接新线,对b的线进行赋值。b的前后应该是a和c
        a.next, c.pre = b, b    # 再连接旧线,对a的后线和c的前线进行赋值。a和c的中间是b

    # 删除当前节点
    def del_self(self):
        a, c = self.pre, self.next  # 先得到被删除节点的前、后节点,问题转化为直接连接a、c节点
        a.next, c.pre = c, a        # 直接连接a、c节点,a的后面应该是c,c的前面应该是a

    ######################################################################################
    """ 问题转化开始 """

    # 变式1:在当前节点的上一个位置插入 b 节点
    def insert_pre(self, b):
        # 直接调用上一个节点的后插函数
        self.pre.insert_next(b)

    # 变式2:删除下一个节点(需保证有下一个)
    def del_next(self):
        # 直接调用下一个节点的自删函数
        self.next.del_self()

    # 变式3:删除上一个节点(需保证有上一个)
    def del_pre(self):
        # 直接调用上一个节点的自删函数
        self.pre.del_self()

    # 变式4:在当前节点前面插入任意个values
    def insert_values_pre(self, values):  # values是一个列表,其元素是简单的值
        # 先拿到当前节点
        p = self  # p是一个临时指针
        # 不停地往p前面插,p不用动
        for val in values:
            p.insert_pre(Node(val))  # 需要用val生成一个新的节点,然后传进去

    # 变式5:在当前节点后面插入任意个values
    def insert_values_next(self, values):  # values是一个列表,其元素是简单的值
        # 直接调用下一个节点的任意插入函数
        self.next.insert_values_pre(values)

    # 变式6: 删除当前节点前面的n个节点(需要你自己保证不会删过头)
    def del_pre_n(self, n):
        # 先拿到当前节点
        p = self  # p是一个临时指针
        # 不停地删除p前面的节点,p不用动
        for _ in range(n):
            p.del_pre()

    # 变式7: 删除当前节点后面的n个节点(需要你自己保证不会删过头)
    def del_next_n(self, n):
        # 先拿到当前节点
        p = self  # p是一个临时指针
        # 不停地删除p后面的节点,p不用动
        for _ in range(n):
            p.del_next()

    # 变式8: 找到n个之后的节点(需要你自己保证后面有n个),然后返回
    def find_next_n(self, n):
        # 先拿到当前节点
        p = self  # p是一个临时指针
        for _ in range(n):
            # 不停地找下一个
            p = p.next
        return p

    # 变式9:删除n个节点后的m个节点
    def del_after_n_count_m(self, n, m):
        # 先找n个节点后的节点
        p = self.find_next_n(n)
        # 直接删
        p.del_next_n(m)

    """ 问题转化结束 """
    #######################################################################################

""" 下面2个是辅助工具函数 """
# 从head到tail打印当前链表(跳过哨兵)
def print_list(head, tail):
    p = head.next  # 跳过头结点
    while p is not tail:  # 下一个不是尾节点
        print(p.val, end=" ")
        p = p.next
    print()

# 构造只有 head / tail 的空双链表
def build_empty_list():
    head = Node()     # head
    tail = Node()     # tail
    head.next = tail  # head --> tail
    tail.pre = head   # tail --> head
    # 此时: head <--> tail
    return head, tail


if __name__ == '__main__':

    # ================== 用例1:基本插入 / 删除 ==================
    print("== 用例1:基本插入 / 删除 ==")

    head, tail = build_empty_list()

    a = Node("A")
    head.insert_next(a)

    b = Node("B")
    a.insert_next(b)

    c = Node("C")
    b.insert_next(c)

    print("初始链表:")
    print_list(head, tail)  # A B C

    b.del_self()
    print("删除 B 后:")
    print_list(head, tail)  # A C

    # ================== 用例2:前插 / 删前删后 ==================
    print("\n== 用例2:前插 / 删前删后 ==")

    head, tail = build_empty_list()

    x = Node("X")
    head.insert_next(x)

    x.insert_pre(Node("L"))
    x.insert_next(Node("R"))
    print("前插 L,后插 R:")
    print_list(head, tail)  # L X R

    x.del_pre()
    print("删除前一个节点:")
    print_list(head, tail)  # X R

    x.del_next()
    print("删除后一个节点:")
    print_list(head, tail)  # X

    # ================== 用例3:批量前插 / 后插 ==================
    print("\n== 用例3:批量插入 ==")

    head, tail = build_empty_list()

    mid = Node("M")
    head.insert_next(mid)

    mid.insert_values_pre(["a", "b", "c"])
    print("批量前插 a b c:")
    print_list(head, tail)  # a b c M

    mid.insert_values_next(["x", "y"])
    print("批量后插 x y:")
    print_list(head, tail)  # a b c M x y

    # ================== 用例4:删除前 n 个 / 后 n 个 ==================
    print("\n== 用例4:删除前 n / 后 n ==")

    head, tail = build_empty_list()

    head.insert_values_next([1, 2, 3, 4, 5, 6])
    print("初始链表:")
    print_list(head, tail)  # 1 2 3 4 5 6

    third = head.next.next.next  # 第 3 个节点 val=3
    third.del_pre_n(2)
    print("删除 3 前面的 1、2:")
    print_list(head, tail)  # 3 4 5 6

    third.del_next_n(1)
    print("删除 3 后面的 4:")
    print_list(head, tail)  # 3 5 6

    # ================== 用例5:find_next_n / del_after_n_count_m ==================
    print("\n== 用例5:查找 + 组合删除 ==")

    head, tail = build_empty_list()

    head.insert_values_next(list("ABCDEFG"))
    print("初始链表:")
    print_list(head, tail)  # A B C D E F G

    first = head.next
    target = first.find_next_n(2)

    print("从 A 往后数 2 个节点(应为 C):", target.val)

    first.del_after_n_count_m(2, 3)
    print("删除 C 后的 D E F:")
    print_list(head, tail)  # A B C G
二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

相关推荐
栏目导航
热门文章
推荐文章

说点什么

分享

扫码加好友,拉您进群
各岗位、行业、专业交流群