Python实现双向链表

Python实现双向链表

双向链表是一种常见的线性数据结构,它允许在任意位置插入、删除、查找节点,具有很好的灵活性和效率。本篇文章将介绍Python如何实现双向链表,包括链表的节点定义、插入删除操作的实现、以及几个示例来说明如何使用双向链表。

链表节点定义

首先,我们需要定义一个双向链表的节点类。节点包含三个属性:前一个节点的指针prev、当前节点的值val、下一个节点的指针next。

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

双向链表的插入操作

在双向链表中,我们可以在指定位置插入一个新节点。插入节点的基本操作包括以下几步:

  1. 新建一个节点;
  2. 将前一个节点的next指向新节点;
  3. 将新节点的prev指向前一个节点,将新节点的next指向后一个节点;
  4. 将后一个节点的prev指向新节点。

具体实现如下:

class DoublyLinkedList:
    def __init__(self):
        """
        Initialize your data structure here.
        """
        self.head = None
        self.tail = None
        self.size = 0

    def addAtIndex(self, index: int, val: int) -> None:
        if index < 0 or index > self.size:  # 处理非法索引
            return

        if index == 0:  # 在头部插入
            self.addAtHead(val)
        elif index == self.size:  # 在尾部插入
            self.addAtTail(val)
        else:
            node = Node(val)
            curr = self.head
            for i in range(index - 1):
                curr = curr.next
            node.prev = curr  # 1. 将前一个节点的next指向新节点
            node.next = curr.next  # 2. 将新节点的prev指向前一个节点,将新节点的next指向后一个节点
            curr.next.prev = node  # 3. 将后一个节点的prev指向新节点
            curr.next = node
            self.size += 1

双向链表的删除操作

在双向链表中,我们可以在指定位置删除一个节点。删除节点的基本操作包括以下几步:

  1. 将前一个节点的next指向后一个节点;
  2. 将后一个节点的prev指向前一个节点。

具体实现如下:

class DoublyLinkedList:
    def __init__(self):
        """
        Initialize your data structure here.
        """
        self.head = None
        self.tail = None
        self.size = 0

    def deleteAtIndex(self, index: int) -> None:
        if index < 0 or index >= self.size:  # 处理非法索引
            return

        if index == 0:  # 删除头部节点
            self.head = self.head.next
            if self.head:  # 注意判断链表是否为空
                self.head.prev = None
            else:
                self.tail = None
        elif index == self.size - 1:  # 删除尾部节点
            self.tail = self.tail.prev
            self.tail.next = None
        else:
            curr = self.head
            for i in range(index):
                curr = curr.next
            curr.prev.next = curr.next  # 1. 将前一个节点的next指向后一个节点
            curr.next.prev = curr.prev  # 2. 将后一个节点的prev指向前一个节点
        self.size -= 1

示例说明

我们来看两个使用示例。

示例1:删除链表中的节点

dll = DoublyLinkedList()
dll.addAtHead(1)
dll.addAtTail(3)
dll.addAtIndex(1, 2)
dll.deleteAtIndex(1)
print(dll.head.val)  # 1
print(dll.head.next.val)  # 3

首先,创建一个双向链表,插入三个节点,值分别为1、2、3。然后,删除第二个节点,即值为2的节点。最后,打印链表头部节点和头部节点的下一个节点,结果分别为1、3。

示例2:反转双向链表

dll = DoublyLinkedList()
dll.addAtHead(1)
dll.addAtTail(3)
dll.addAtIndex(1, 2)

# 反转链表
new_head = dll.tail
while new_head:
    print(new_head.val)
    new_head = new_head.prev

首先,创建一个双向链表,插入三个节点,值分别为1、2、3。然后,使用while循环反转链表,按照逆序打印链表节点的值。最后的输出结果为3、2、1,说明链表已经被成功反转。

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

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

相关文章

  • java简单读取properties配置文件的方法示例

    下面是关于“java简单读取properties配置文件的方法示例”的完整攻略: 什么是properties文件 在Java开发中,properties文件是一种常用的配置文件,通常用于存储一些应用程序运行时需要用到的配置信息,比如数据库连接信息、日志输出等等。properties文件是以键值对的形式存储数据,其中键和值之间以等号“=”分隔,每一行表示一个键…

    other 2023年6月25日
    00
  • springboot maven 项目打包jar 最后名称自定义的教程

    Spring Boot Maven项目打包jar最后名称自定义的教程 在Spring Boot项目中,使用Maven进行打包时,默认生成的jar文件名称是根据项目的artifactId和version来命名的。如果你想自定义生成的jar文件名称,可以按照以下步骤进行操作: 打开项目的pom.xml文件。 在<build>标签下添加以下配置: xm…

    other 2023年10月13日
    00
  • C语言深入详解四大内存函数的使用

    C语言深入详解四大内存函数的使用攻略 1. malloc函数 malloc函数用于在堆内存中动态分配指定大小的内存空间,并返回一个指向该内存空间的指针。其函数原型如下: void* malloc(size_t size); 使用示例: #include <stdio.h> #include <stdlib.h> int main() …

    other 2023年8月2日
    00
  • Go语言利用接口实现链表插入功能详解

    Go语言利用接口实现链表插入功能详解 简介 本篇攻略将会介绍如何使用Go语言的接口来实现链表的插入功能。链表是一种常用的数据结构,可以方便地在其中插入和删除元素。通过实现链表的插入功能,我们可以更全面地理解接口在Go语言中的应用。 链表结构体 在实现链表之前,我们需要定义一个链表的结构体。该结构体包含两个字段,一个是链表的元素值,另一个是后继指针。 type…

    other 2023年6月27日
    00
  • 一键快速关机/重启和登出Win8的实用小技巧

    下面是关于“一键快速关机/重启和登出Win8的实用小技巧”的详细攻略。 一、快速关机和重启 方法一:使用快捷键 直接按下键盘上的「Win+I」快捷键,打开 Windows 8 的设置菜单; 点击「电源」选项,会出现「关机」和「重启」的选项,点击即可关机或重启。 方法二:使用命令行 打开命令提示符,可以通过 【Win + R】 键调出运行窗口,输入 cmd 后…

    other 2023年6月27日
    00
  • 实现一个简单的虚拟DOM

    实现一个简单的虚拟DOM 虚拟DOM是前端开发中常用的一种技术,它可以提高页面渲染的效率,减少DOM操作的次数。本文将提供一个完整的攻略,包括虚拟DOM的基本原理、实现方法和两个示例说明。 基本原理 虚拟DOM的基本原理是将页面的DOM结构抽象成一个JavaScript对象,称为虚拟DOM。当页面需要更新时,先对虚拟DOM进行操作,然后将虚拟DOM与页面的实…

    other 2023年5月5日
    00
  • Android自定义控件之仿优酷菜单

    Android自定义控件之仿优酷菜单 简介 本文将介绍如何通过自定义ViewGroup实现仿优酷菜单的效果,主要涉及以下几个方面: 自定义ViewGroup的基本概念 仿优酷菜单的实现过程 示例展示说明 自定义ViewGroup ViewGroup是View的子类,可以包含多个子View,是Android App中布局最常用的容器之一。自定义ViewGrou…

    other 2023年6月25日
    00
  • 哔哩哔哩如何自定义视频操作面板 哔哩哔哩自定义视频操作面板的方法

    哔哩哔哩如何自定义视频操作面板 在哔哩哔哩上,用户可以自定义视频操作面板,以满足个人需求。自定义视频操作面板的方法如下: 方法一:通过网页端设置 打开哔哩哔哩官网,在登录后进入个人中心页面 在个人中心页面,点击「设置」选项进入设置页面 在设置页面,点击「播放器设置」选项 在播放器设置页面,可以看到「视频操作面板布局」选项 点击「视频操作面板布局」选项,可以看…

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