Python代码实现双链表

Python代码实现双链表

1. 双链表概述

双链表(doubly linked list)是一种常见的链式数据结构,每个节点有两个指针,一个指向前一个节点,一个指向后一个节点。双链表相比于单链表,虽然存储空间更大,但是它可以更方便地获取前一个节点,所以它具有非常重要的应用价值,例如在LRU缓存算法中就用到了双链表。

2. 双链表的实现

双链表的实现可以考虑使用类的形式,每个节点作为类的一个实例,节点类中包括该元素的值(value)以及两个指针,分别指向前一个节点(prev)和后一个节点(next)。具体实现流程可以分为以下几步:

2.1 定义双链表节点类

我们可以使用Python的面向对象编程思想,定义一个双链表节点类,其中包含value、prev(前一个节点)、next(后一个节点)三个属性。代码如下所示:

class Node: 
    def __init__(self, value=None, prev=None, next=None): 
        self.value = value 
        self.prev = prev 
        self.next = next 

2.2 定义双链表类

双链表类需要包含头节点和尾节点两个属性,以及若干个双链表节点。首先定义构造方法,用于初始化头节点和尾节点:

class MyLinkedList: 
    def __init__(self): 
        self.head = Node() 
        self.tail = Node() 
        self.head.next = self.tail 
        self.tail.prev = self.head 

然后,定义其他的基本方法,包括获取链表长度、在链表指定位置插入节点、删除指定节点、获取指定位置节点等。

2.3 在链表指定位置插入节点

在双链表中,插入节点比较方便,我们只需要将插入节点的prev指向前面的节点,将插入节点的next指向后面的节点,再将前面的节点的next指向插入节点,后面的节点的prev指向插入节点即可。代码如下所示:

def addAtIndex(self, index: int, value) -> None:
    if index > self.get_length() or index < 0:
        return
    node = Node(value)
    curr = self.head
    for i in range(index): # 遍历index前的节点
        curr = curr.next
    node.prev = curr
    node.next = curr.next 
    curr.next.prev = node 
    curr.next = node 

2.4 删除指定节点

在双链表中删除节点也比较简单,我们只需要将待删除节点的前一个节点的next指向待删除节点的后一个节点,待删除节点的后一个节点的prev指向待删除节点的前一个节点即可。代码如下:

def deleteAtIndex(self, index: int) -> None:
    if index >= self.get_length() or index < 0:
        return
    curr = self.head 
    for i in range(index): # 遍历到index节点
        curr = curr.next
    curr.next.prev = curr.prev
    curr.prev.next = curr.next

2.5 获取指定位置节点

根据索引获取链表中的某个节点的方法同样非常简单,我们只需要遍历到目标节点位置即可。代码如下:

def get(self, index: int) -> int:
    if index >= self.get_length() or index < 0:
        return -1
    curr = self.head 
    for i in range(index+1):
        curr = curr.next
    return curr.value

3. 示例说明

下面给出两个使用示例,以便读者更好理解双链表的实现。

3.1 示例一

以下是一个在双链表中插入、删除、获取指定节点等操作的示例:

# 初始化双链表
linked_list = MyLinkedList()

# 在链表尾部添加节点
linked_list.addAtTail(1)
linked_list.addAtTail(2)
linked_list.addAtTail(3)
# 此时链表为 [1, 2, 3]

# 在链表指定位置插入节点
linked_list.addAtIndex(1, 4)
# 此时链表为 [1, 4, 2, 3]

# 删除链表指定位置节点
linked_list.deleteAtIndex(2)
# 此时链表为 [1, 4, 3]

# 获取链表指定位置节点
linked_list.get(1) # 返回4

3.2 示例二

以下是一个在LeetCode题目中使用双链表解决问题的示例。LeetCode第707题要求实现一个MyLinkedList类,支持添加(尾部)、添加(指定位置)、删除、获取等操作。代码如下:

class MyLinkedList:
    def __init__(self):
        """
        Initialize your data structure here.
        """
        self.head = Node(0)
        self.tail = Node(0)
        self.head.next = self.tail
        self.tail.prev = self.head
        self.size = 0

    def get(self, index: int) -> int:
        """
        Get the value of the index-th node in the linked list. If the index is invalid, return -1.
        """
        if index < 0 or index >= self.size:
            return -1
        curr = self.head
        for i in range(index + 1):
            curr = curr.next
        return curr.value

    def addAtHead(self, val: int) -> None:
        """
        Add a node of value val before the first element of the linked list. After the insertion, the new node will be the first node of the linked list.
        """
        node = Node(val, self.head, self.head.next)
        self.head.next.prev = node
        self.head.next = node
        self.size += 1

    def addAtTail(self, val: int) -> None:
        """
        Append a node of value val to the last element of the linked list.
        """
        node = Node(val, self.tail.prev, self.tail)
        self.tail.prev.next = node
        self.tail.prev = node
        self.size += 1

    def addAtIndex(self, index: int, val: int) -> None:
        """
        Add a node of value val before the index-th node in the linked list. If index equals to the length of linked list, the node will be appended to the end of linked list. If index is greater than the length, the node will not be inserted.
        """
        if index > self.size:
            return
        if index < 0:
            index = 0
        curr = self.head
        for i in range(index + 1):
            curr = curr.next
        node = Node(val, curr.prev, curr)
        curr.prev.next = node
        curr.prev = node
        self.size += 1

    def deleteAtIndex(self, index: int) -> None:
        """
        Delete the index-th node in the linked list, if the index is valid.
        """
        if index < 0 or index >= self.size:
            return
        curr = self.head
        for i in range(index + 1):
            curr = curr.next
        curr.prev.next = curr.next
        curr.next.prev = curr.prev
        self.size -= 1

在LeetCode上测试该代码,发现通过所有测试用例,说明了Python的双链表实现充分具备实际使用的能力。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Python代码实现双链表 - Python技术站

(0)
上一篇 2023年6月27日
下一篇 2023年6月27日

相关文章

  • Android应用的多语言支持的实现方法

    Android应用的多语言支持的实现方法 在Android应用中实现多语言支持可以让应用适应不同地区和语言的用户。下面是一种常用的实现方法: 1. 准备多语言资源文件 首先,需要为每种语言准备对应的字符串资源文件。在res目录下创建一个新的目录,命名为values-xx,其中xx是语言的ISO 639-1代码,例如values-en表示英语,values-z…

    other 2023年8月5日
    00
  • css控制元素背景透明度总结

    CSS控制元素背景透明度总结 在前端开发过程中,控制元素背景透明度是一个经常会用到的技术。本文将介绍CSS中控制元素背景透明度的几种方法和注意事项。 透明度实现方法 opacity属性 opacity是CSS中用来设置元素透明度的属性,其值从0.0(完全透明)到1.0(完全不透明)。下面是一个例子: div { opacity: 0.5; } 使用opaci…

    其他 2023年3月28日
    00
  • vant快速上手

    Vant是一款基于Vue.js的移动端UI组件库,提供了丰富的组件和样式,可以快速构建高质量的移动端应用。以下是关于Vant快速上手的详细攻略: Vant快速上手 以下是使用Vant快速上手的步骤: 安装Vant 可以使用npm或yarn安装Vant: npm install vant -S 或 yarn add vant 引入Vant 在Vue.js项目中…

    other 2023年5月9日
    00
  • 关于linux服务器hosts文件配置详解

    下面我将详细讲解关于Linux服务器hosts文件配置的完整攻略。 什么是hosts文件 hosts文件是一个简单的文本文件,它被用来将IP地址和域名进行简单的映射。在Linux系统中hosts文件位于/etc/hosts路径下,它可以被用来配置DNS解析对于一些本地站点的自定义。 hosts文件的格式 在hosts文件中,每行表示一条IP地址和域名的映射关…

    other 2023年6月25日
    00
  • Android编程实现获得内存剩余大小与总大小的方法

    Android编程实现获得内存剩余大小与总大小的方法 在Android编程中,我们可以使用ActivityManager类和MemoryInfo类来获取设备的内存信息。下面是实现获得内存剩余大小与总大小的方法的完整攻略。 步骤一:导入必要的类和包 首先,在你的Android项目中,确保已经导入了以下类和包: import android.app.Activi…

    other 2023年8月1日
    00
  • 解析rust中的struct

    解析 Rust 中的 Struct,一般需要考虑以下几个方面: 格式定义 在 Rust 中,struct 具体的格式是通过 struct 关键字定义的。 struct StructName { attribute1: DataType1, attribute2: DataType2, … } 其中 StructName 是定义的 struct 的名称,a…

    other 2023年6月27日
    00
  • sqlserver replace函数 批量替换数据库中指定字段内指定字符串参考方法

    替换数据库中特定字段内的指定字符串可以方便地使用SQL Server内置函数 REPLACE。 REPLACE函数用于在字符串中搜索指定的子字符串,并用新的子字符串替换它们。该函数可以被用于不同的数据类型,例如char、varchar、text和 ntext等等。 下面是一些示例,说明如何使用 REPLACE 函数在 SQL Server 中批量替换数据表字…

    other 2023年6月25日
    00
  • ntfs蓝屏怎么修复? Win11修复 NTFS 文件系统蓝屏死机的技巧

    下面是针对NTFS蓝屏的修复攻略: 1. 前置条件 在进行下面的修复操作之前,请确保: 您的计算机已经进入到了蓝屏错误的状态 您有本机Win11系统安装光盘或USB安装盘 您已经备份了重要文件和数据,因为此操作可能会将数据损坏或丢失 2. 从Win11安装盘进入修复模式 首先,需要从Win11安装盘进入到修复模式。具体步骤如下: 插入Win11系统安装盘或U…

    other 2023年6月27日
    00
合作推广
合作推广
分享本页
返回顶部