首页 > 编程语言 >python实现链表(单链,双链)

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

时间:2023-08-20 11:44:28浏览次数:30  
标签:__ None python self next 链表 双链 data 指针

# 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

标签:__,None,python,self,next,链表,双链,data,指针
From: https://www.cnblogs.com/I-LOVE-YOU-hzj/p/17643790.html

相关文章

  • PYTHON 快速分割CSV
    fromopenpyxlimportWorkbookimportpandasaspdimportnumpyasnpimportsys,time,re,csvpath="f:/te/qh.csv"path1="F:/BaiduNetdiskDownload\行政许可/行政许可/行政许可.csv"##num_rows=sum(1forrowinopen(path,encoding="utf-8"))##......
  • python
    pythonclassBook:  def__init__(self,title,author,year):    self.title=title    self.author=author    self.year=yearclassLibrary:  def__init__(self):    self.books=[]  defadd_book(self,book):    se......
  • Python学习:迭代器与生成器的深入解析
    函数在Python中扮演着重要角色,不仅可以封装代码逻辑,还能通过迭代器和生成器这两种强大的技术,实现更高效的数据处理和遍历。本篇博客将深入探讨Python函数的迭代器和生成器,结合实际案例为你揭示它们的神奇,以及如何巧妙地应用迭代器和生成器来解决实际问题。迭代器:数据的遍历之道迭代......
  • 【python】如何将枚举指针传递至dll接口中
    在Python中,可以使用 ctypes 模块来将枚举指针传递给DLL接口。以下是一个简单的示例代码,演示了如何在Python中使用 ctypes 将枚举指针传递给DLL接口:importctypes#定义枚举类型classMyEnum(ctypes.Structure):_fields_=[("value",ctypes.c_int)]#加载D......
  • python+playwright 学习-75 playwright 通过浏览器发送post请求
    前言page.goto()可以通过浏览器直接发get请求,playwright也可以支持通过浏览器发送post请求。page.goto()使用page.goto()访问网站的时候,实际上是有返回值的,可以获取到response对象fromplaywright.sync_apiimportsync_playwright,expectwithsync_playwright()asp:......
  • 知识图谱入门:使用Python创建知识图,分析并训练嵌入模型
    本文中我们将解释如何构建KG、分析它以及创建嵌入模型。构建知识图谱加载我们的数据。在本文中我们将从头创建一个简单的KG。 https://avoid.overfit.cn/post/7ec9eb11e66c4b44bd2270b8ad66d80d......
  • python创建虚拟环境【其它人项目】
    download他人项目-创建虚拟环境这是别人的项目打开pycahrm的终端,创建虚拟环境名字为venv【python-mvenvvenv】此时文件目录多出一个venv目录设置里面选择虚拟环境关闭pycahrm里面终端,重开会自动进入虚拟环境里面结束!......
  • *【学习笔记】(10) 块状链表
    块状链表(尚未完善)对于线性表,可以\(O(1)\)的访问,但是插入和删除操作是\(O(n)\)对于链表,可以\(O(1)\)的进行插入和删除,但是是\(O(n)\)的访问。于是本着分块的思想,有了块状链表。大概长这个样子。每个块的大小数量级在\(O(\sqrt{n})\),块数的量级\(O(\sqrt{n})\)主......
  • python 垃圾回收
    【第1题】Pythonn内存管理以及垃圾回收机制-武沛齐-博客园(cnblogs.com)https://www.bilibili.com/video/BV1F54114761/  元祖 总结:为了回收内存,每个对象都加入了refchain双向环向链表,对象被引用+1,del掉-1,等于0内存就被回收,这个叫引用计数器ob_refcnt;但是像列......
  • python 小案例正则表达式
    正则表达式是一种用于匹配、查找和替换文本的强大工具。在提取网页中的目标数据时,可以使用正则表达式来搜索和匹配特定模式的文本。以下是一个使用正则表达式提取网页中的目标数据的示例代码:importre#网页源代码html="""<divclass="title">正则表达式教程</div><divc......