python实现链表(单链,双链)

发布时间 2023-08-20 11:44:30作者: A实沈
# code:utf-8
# createTime:2023.8.17

# -----------------------------------------------------------------------------
class Node:
    """
    节点类,每个数据就是一个节点,
    包含一个数据位和一个指针位,
    指针指向下一个数据的内存地址
    """
    def __init__(self, data=None):
        # 数据位
        self.data = data
        # 指针位
        self.next = None

    # 输出节点的值
    def __str__(self):
        return str(self.data)

# -----------------------------------------------------------------------------
# 为链表定义的错误类型 ---所需删除元素未找到
class DeleteNotFindError(Exception):
    def __init__(self, message):
        super().__init__(message)



# -----------------------------------------------------------------------------

class Link:
    """单向链表"""

    def __init__(self):
        self.head = None    # 头指针
        self.END = None     # 尾指针
        self._size = 0      # 链表大小的计数变量

    # function -> 追加数据
    def append(self, data)->None:

        # 初始化一个节点
        node = Node(data = data)

        # 判断链表是否为空,如果链表不为空
        if self.END:
            self.END.next = node    # 将指针指向下一个位置
            self.END = node         # 将数据存入内存

        # 如果链表为空
        else:
            self.head = node    # 头指针指向第一个数据
            self.END = node     # 尾指针指向第一个数据

        # 计数变量的自增
        self._size += 1

    # function -> 获取链表大小
    def getsize(self)->int:
        return int(self._size)

    # 返回生成器
    def __iter__(self):
        insert = self.head          # 获取头指针

        # 判断下一个内存地址是否存在
        while insert:
            val = insert.data       # 获取内存地址处存放的数据
            insert = insert.next    # 将指针指向下一个地址
            yield val               # 使用生成器yield返回数据

    # function -> 删除节点
    def delete(self, data):
        # 此处采用双指针模式进行查找

        insert = self.head          # 前指针,指向查找元素的前一位
        end = self.head             # 后指针,指向查找元素

        # 顺着链表查下去,时间复杂度位 O(n),如果后指针有值
        while end:

            # 如果值相等
            if end.data == data:

                # 如果需查找元素在开头
                if end == self.head:
                    self.head = self.head.next  # 直接修改头指针的指向
                else:
                    insert.next = end.next      # 将前指针的指向修改为后指针的下一位

                self._size -= 1                 # 计数变量自减

                # 利用return结束循环
                return

            # 双指针依次指向所有节点,知道查找到
            insert = end
            end = end.next

        else:
            # 输出错误提示
            raise DeleteNotFindError(f"Not find {data} in Link")

    # function -> 搜索节点
    def find(self, data)->bool:

        # 这里直接套用iter方法
        for i in self.__iter__():

            # 找到节点
            if i == data:
                return True     # 返回True

        else:
            return False        # 未找到节点返回False

    # function -> 清空链表
    def clear(self):
        """clear the entire Linklist"""
        self.head = None
        self.END = None
        self._size = 0

# -----------------------------------------------------------------------------

class Nodes(object):

    def __init__(self, data=None, next=None, prev=None):
        self.data = data        # 节点数据
        self.next = next        # 下一节点指针
        self.prev = prev        # 上一节点指针

# -----------------------------------------------------------------------------

class DoubleLink(object):

    def __init__(self):
        self.head = None        # 头节点
        self.end = None         # 尾节点
        self._size = 0          # 计数

    # function -> 添加元素
    def append(self, data):
        nodes = Nodes(data, None, None)
        if self.head is None:
            self.head = nodes
            self.end = self.head
        else:
            nodes.prev = self.end
            self.end.next = nodes
            self.end = nodes
            self._size += 1

    # function -> 删除元素
    def delete(self, data):
        # 删除元素分为四种不同的情况,这里要进行分类讨论
        # 第一种,链表为空
        current = self.head
        if current is None:
            # 输出错误提示
            raise DeleteNotFindError(f"Not find {data} in DoubleLink")
        # 第二种,要删除的节点位于链表头部
        elif current.data == data:
            self.head = current.next
            self.head.prev = None
            self._size -= 1

        elif self.end.data == data:
            self.end = self.end.prev
            self.end.next = None
            self._size -= 1
        else:
            while current:
                if current.data == data:
                    current.prev.next = current.next
                    current.next.prev = current.prev
                    self._size -= 1
                    return

                current = current.next
            else:
                raise DeleteNotFindError(f"Not find {data} in DoubleLink")

    # function -> 获取链表节点数
    def getsize(self):
        return int(self._size)

    # 返回生成器
    def __iter__(self):
        insert = self.head          # 获取头指针

        # 判断下一个内存地址是否存在
        while insert:
            val = insert.data       # 获取内存地址处存放的数据
            insert = insert.next    # 将指针指向下一个地址
            yield val               # 使用生成器yield返回数据

 

说明:Node是单向链表的节点类,Nodes则是双向节点类

使用实例:

from main import *  # 导入链表代码所在文件

# 单链表
test = Link()
for i in range(1,10):
    test.append(i)
for i in test:
    print(i)

print("__________________________")
# 双链表
test = DoubleLink()
for i in range(1,10):
    test.append(i)

test.delete(5)
for i in test:
    print(i)

结果:

1
2
3
4
5
6
7
8
9
__________________________
1
2
3
4
6
7
8
9