当前位置: 首页 > news >正文

Python----数据结构(单链表:节点,是否为空,长度,遍历,添加,删除,查找)

一、链表

        链表是一种线性数据结构,由一系列按特定顺序排列的节点组成,这些节点通过指针相互连接。每个节点包含两部分:元素和指向下一个节点的指针。其中,最简单的形式是单向链表,每个节点含有一个信息域和一个指针域,该指针指向链表中的下一个节点,最后一个节点则指向一个空值。

1.1、Python中的链表

•        大部分都是用C语言实现链表,因为C有指针,可以很方便的控制内存,很轻易就可以实现链 表,在C/C++中,通常采用“指针+结构体”来实现链表。

•        Python是一门动态语言,可以直接把对象赋值给新的变量,我们采用“引用+类”来实现 链表。

•        结构:data为自定义的数据,next为下一个节点的地址。

•        链表的种类:单向链表、双向链表、单向循环链表、双向循环链表。 

1.2、基本元素

节点:每个节点有两个部分,左边称为值域,存放用户数据;右边部分称为指针域,用来存 放指向下一个元素的指针。

Head:head节点永远指向第一个节点。

Tail:tail节点永远指向最后一个节点。

None:链表中最后一个节点的指针域为None。

二、基本操作

2.1、节点的创建

class Node:
    def __init__(self, data):
        # 初始化节点,包含数据和指向下一个节点的指针
        self.data = data
        self.next = None  

2.2、初始化单向链表

class LinkList:
    def __init__(self, node=None):
        # 初始化链表,头指针指向第一个节点(默认为None)
        self.__head = node

2.3、判断是否为空

    def is_empty(self):
        # 检查链表是否为空
        return self.__head == None

2.4、链表长度

    def length(self):
        # 计算链表的长度
        current = self.__head
        count = 0
        while current != None:
            count += 1
            current = current.next
        return count

2.5、遍历链表 

    def travel(self):
        # 遍历链表并打印每个节点的数据
        current = self.__head
        while current != None:
            print(current.data)
            current = current.next

2.4、插入节点

2.4.1、头节点

    def add(self, data):
        # 在链表头部添加新节点
        new_node = Node(data)
        new_node.next = self.__head
        self.__head = new_node

2.4.2、中间节点

    def insert(self, pos, data):
        # 在指定位置插入新节点
        if pos > self.length() - 1:
            self.append(data)  # 如果位置超出范围,添加到尾部
        elif pos <= 0:
            self.add(data)  # 如果位置小于等于0,添加到头部
        else:
            new_node = Node(data)
            pre = self.__head
            count = 0
            while count < pos - 1:
                count += 1
                pre = pre.next
            new_node.next = pre.next  # 将新节点的next指向当前节点的next
            pre.next = new_node  # 将前一个节点的next指向新节点

2.4.3、尾节点

    def append(self, data):
        # 在链表尾部添加新节点
        new_node = Node(data)
        if self.is_empty():
            self.__head = new_node
        else:
            current = self.__head
            while current.next != None:
                current = current.next
            current.next = new_node

 

2.5、删除节点

    def remove(self, data):
        # 移除链表中指定数据的节点
        current = self.__head
        pre = None
        while current != None:
            if current.data == data:
                if current == self.__head:
                    self.__head = current.next  # 如果是头节点,更新头指针
                else:
                    pre.next = current.next  # 将前一个节点的next指向当前节点的next
                break
            else:
                pre = current
                current = current.next

2.6、查找节点

    def serch(self, data):
        # 查找链表中是否存在指定数据
        current = self.__head
        while current != None:
            if current.data == data:
                return True  # 找到数据,返回True
            else:
                current = current.next
        return False  # 遍历完成未找到数据,返回False

三、链表的特点

1、动态数据集合:链表允许动态的添加和删除元素,这使得它们在处理未知数量或频繁变 化的数据集时非常有用。

2、元素顺序:链表可以按照插入顺序来保持元素的顺序,这对于需要维护元素插入顺序的 应用程序非常有用。

3、 内存效率:与数组相比,链表在内存使用上更为高效,因为它们不需要连续的内存空间。 链表通过节点之间的指针来连接元素,这样可以更有效地利用内存空间。

4、避免数组扩容:数组在初始化时需要指定大小,如果超出大小,则需要扩容,这是一个 昂贵的操作。链表则可以避免这个问题,因为它们可以动态地增长。

四、单向链表的缺点

1、只能从头遍历到尾或者从尾遍历到头(一般从头到尾)。

2、链表相连的过程是单向的。实现的原理是上一个链表中有一个指向下一个的引用。

3、 我们可以轻松的到达下一个节点, 但是回到前一个节点是很难的。但是, 在实际开发中, 经 常会遇到需要回到上一个节点的情况。

举个例子:

        假设一个文本编辑用链表来存储文本。每一行用一个String对象存储在链表的 一个节点中。当编辑器用户向下移动光标时, 链表直接操作到下一个节点即可。但是当用 于将光标向上移动呢? 这个时候为了回到上一个节点, 我们可能需要从头开始, 依次走到 想要的节点上。

五、完整代码 

class Node:
    def __init__(self, data):
        # 初始化节点,包含数据和指向下一个节点的指针
        self.data = data
        self.next = None

class LinkList:
    def __init__(self, node=None):
        # 初始化链表,头指针指向第一个节点(默认为None)
        self.__head = node

    def is_empty(self):
        # 检查链表是否为空
        return self.__head == None

    def length(self):
        # 计算链表的长度
        current = self.__head
        count = 0
        while current != None:
            count += 1
            current = current.next
        return count

    def travel(self):
        # 遍历链表并打印每个节点的数据
        current = self.__head
        while current != None:
            print(current.data)
            current = current.next

    def add(self, data):
        # 在链表头部添加新节点
        new_node = Node(data)
        new_node.next = self.__head
        self.__head = new_node

    def append(self, data):
        # 在链表尾部添加新节点
        new_node = Node(data)
        if self.is_empty():
            self.__head = new_node
        else:
            current = self.__head
            while current.next != None:
                current = current.next
            current.next = new_node

    def insert(self, pos, data):
        # 在指定位置插入新节点
        if pos > self.length() - 1:
            self.append(data)  # 如果位置超出范围,添加到尾部
        elif pos <= 0:
            self.add(data)  # 如果位置小于等于0,添加到头部
        else:
            new_node = Node(data)
            pre = self.__head
            count = 0
            while count < pos - 1:
                count += 1
                pre = pre.next
            new_node.next = pre.next  # 将新节点的next指向当前节点的next
            pre.next = new_node  # 将前一个节点的next指向新节点

    def remove(self, data):
        # 移除链表中指定数据的节点
        current = self.__head
        pre = None
        while current != None:
            if current.data == data:
                if current == self.__head:
                    self.__head = current.next  # 如果是头节点,更新头指针
                else:
                    pre.next = current.next  # 将前一个节点的next指向当前节点的next
                break
            else:
                pre = current
                current = current.next

    def serch(self, data):
        # 查找链表中是否存在指定数据
        current = self.__head
        while current != None:
            if current.data == data:
                return True  # 找到数据,返回True
            else:
                current = current.next
        return False  # 遍历完成未找到数据,返回False

if __name__ == '__main__':
    linklist = LinkList()
    linklist.add(10)  # 添加节点10
    linklist.add(20)  # 添加节点20
    linklist.append(100)  # 在尾部添加节点100
    linklist.add(30)  # 添加节点30
    linklist.add(40)  # 添加节点40

    print(linklist.is_empty())  # 检查链表是否为空
    print(linklist.length())  # 输出链表长度
    print('*****************')
    linklist.remove(30)  # 移除节点30
    # linklist.travel()  # 遍历链表并打印节点数据
    print(linklist.serch(40))  # 查找节点40是否存在
    # linklist.travel()  # 遍历链表并打印节点数据

六、思维导图 

http://www.dtcms.com/a/23446.html

相关文章:

  • VINS-mono代码笔记
  • Java 运行时常量池笔记(详细版
  • 第150场双周赛:好数字之和、分割正方形 Ⅰ、分割正方形 Ⅱ、最短匹配字符串
  • 第1章大型互联网公司的基础架构——1.2 客户端连接机房的技术1:DNS
  • Java基于 SpringBoot+Vue的微信小程序跑腿平台V2.0(附源码,文档)
  • css里flex+margin布局
  • iOS 中使用 FFmpeg 进行音视频处理
  • 机器学习数学基础:27.数字特征
  • 深入解析 iOS 视频录制(一):录制管理核心MWRecordingController 类的设计与实现
  • 网络安全不分家 网络安全不涉及什么
  • el-input无法输入0.0001的小数,自动转换为0在vue3中的bug
  • 【SpringBoot注解失效】@注解为什么不生效?
  • home assistant ddns动态域名解析插件
  • AWS上Amazon Redshift用Zoominfo API验证公司基本信息数据正确性检查设计方案
  • Vue 前端开发中的路由知识:从入门到精通
  • STM32外设SPI FLASH应用实例
  • 2.16日学习总结
  • Flutter 记一次疑难杂症
  • 【HUSTOJ 判题机源码解读系列04】判题机常见技术选择方案
  • 响应式布局学习笔记
  • BT401双模音频蓝牙模块如何开启ble的透传,有什么注意事项
  • 从零到一:Spring Boot 与 RocketMQ 的完美集成指南
  • GPT-4o悄然升级:能力与个性双突破,AI竞技场再掀波澜
  • Go 模块管理工具 `go mod tidy` 和 `go.sum` 文件详解
  • 在 Android 上自定义编译 FFmpeg
  • 嵌入式Linux系统SPI驱动移植专题详解(3000+字图文实战指南)
  • 康耐视CAM-CIC-10MR-10-GC工业相机
  • 《TSP6K数据集进行交通场景解析》学习笔记
  • 计算机网络(4)TCP断开
  • MySQL中ddl操作或创建索引防止锁表的一些建议或解决方案