Python数据结构之双向链表详解

Python数据结构之双向链表详解

什么是双向链表?

在计算机科学中,双向链表是链表的一种,每个结点除了储存下一个结点的指针外,还储存着前一个结点的指针。这个“前进”指针被称为“ next指针”,而“后退”指针被称为“previous指针”。

双向链表和单向链表的区别在于,单向链表的每个结点只储存一个指向下一个结点的指针,而双向链表储存了前一个和后一个结点的指针。

双向链表的基本形式

下面是一个基本的双向链表结构的代码示例:

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

class DoublyLinkedList:
    def __init__(self):
        self.head = None

其中,Node类表示链表的结点,包含属性data、next和prev。DoublyLinkedList类表示一个双向链表。在初始化时,它有一个头指针head,初始为None。

双向链表的基本操作

在链表头插入一个结点

从头部插入一个新节点需要执行以下步骤:

  1. 创建一个新节点
  2. 将新节点的next指针指向旧的头结点
  3. 将旧的头结点的prev指针指向新节点
  4. 将新节点赋值为头结点

示例如下:

def insert_at_beg(self, data):
    new_node = Node(data)
    if self.head is None:
        self.head = new_node
    else:
        new_node.next = self.head
        self.head.prev = new_node
        self.head = new_node

在链表尾插入一个结点

从尾部插入一个新节点需要执行以下步骤:

  1. 创建一个新节点
  2. 如果链表为空,将新节点赋值给头结点;否则找到链表的最后一个节点并将其next指向新节点
  3. 将新节点的prev指针指向链表的最后一个节点

示例如下:

def insert_at_end(self, data):
    new_node = Node(data)
    if self.head is None:
        self.head = new_node
    else:
        temp = self.head
        while(temp.next is not None):
            temp = temp.next

        temp.next = new_node
        new_node.prev = temp

在指定位置插入一个结点

在指定位置插入新节点需要执行以下步骤:

  1. 创建一个新的节点
  2. 找到要插入的位置
  3. 将新节点的next指向插入位置的节点,将插入位置节点的prev指针指向新节点
  4. 将新节点的prev指向插入位置的前一个节点,将前一个节点的next指针指向新节点

示例如下:

def insert_at_position(self, data, position):
    new_node = Node(data)
    if self.head is None:
        self.head = new_node
    elif position == 0:
        new_node.next = self.head
        self.head.prev = new_node
        self.head = new_node
    else:
        temp = self.head
        for i in range(position-1):
            temp = temp.next
        new_node.next = temp.next
        new_node.prev = temp
        if temp.next is not None:
            temp.next.prev = new_node
        temp.next = new_node

删除链表头部结点

从链表头部删除一个节点需要执行以下步骤:

  1. 判断链表是否为空
  2. 如果链表长度为1,将头结点置为None
  3. 否则,将头结点的下一个节点作为新的头节点,将新头节点的prev指针设置为None

示例如下:

def delete_at_beg(self):
    if self.head is None:
        return None
    if self.head.next is None:
        temp = self.head
        self.head = None
        return temp.data
    temp = self.head
    self.head = self.head.next
    self.head.prev = None
    return temp.data

删除链表尾部结点

从链表尾部删除一个节点需要执行以下步骤:

  1. 判断链表是否为空
  2. 如果链表长度为1,将头结点置为None
  3. 否则,找到链表最后一个节点,将倒数第二个节点的next指针置为空

示例如下:

def delete_at_end(self):
    if self.head is None:
        return None
    if self.head.next is None:
        temp = self.head
        self.head = None
        return temp.data
    temp = self.head
    while(temp.next is not None):
        temp = temp.next
    temp.prev.next = None
    return temp.data

删除指定位置的结点

在指定位置删除节点需要执行以下步骤:

  1. 判断链表是否为空
  2. 如果删除的节点是头结点,将头节点的下一个节点作为新的头节点,并将新的头节点的prev指针置为空
  3. 如果删除的节点是尾节点,将倒数第二个节点的next指针置为空
  4. 否则,找到要删除的节点,并重置其前后节点的prevnext指针

示例如下:

def delete_at_position(self, position):
    if self.head is None:
        return None
    if position == 0:
        if self.head.next is None:
            temp = self.head
            self.head = None
            return temp.data
        temp = self.head
        self.head = self.head.next
        self.head.prev = None
        return temp.data
    else:
        count = 0
        temp = self.head
        while(temp is not None and count < position):
            temp = temp.next
            count += 1
        if temp is None:
            return None
        if temp.next is None:
            temp.prev.next = None
        else:
            temp.prev.next = temp.next
            temp.next.prev = temp.prev
        return temp.data

示例

插入元素

插入元素并打印链表

if __name__ == '__main__':
    dll = DoublyLinkedList()
    dll.insert_at_end(10)
    dll.insert_at_end(20)
    dll.insert_at_end(30)
    dll.insert_at_end(40)
    dll.insert_at_position(50, 2)

    temp = dll.head
    while(temp):
        print(temp.data, end=' ')
        temp = temp.next

输出:

10 20 50 30 40 

删除元素

删除元素并打印链表

if __name__ == '__main__':
    dll = DoublyLinkedList()
    dll.insert_at_end(10)
    dll.insert_at_end(20)
    dll.insert_at_end(30)
    dll.insert_at_position(15, 1)

    dll.delete_at_beg()
    dll.delete_at_position(1)
    dll.delete_at_end()

    temp = dll.head
    while(temp):
        print(temp.data, end=' ')
        temp = temp.next

输出:

20 

总结

双向链表的优势在于可以同时向前和向后遍历,但是相应的空间复杂度更高,需要在每个节点上维护prev指针。以上是双向链表的基本操作,仔细理解了这些操作,对于理解更为复杂的链表操作会有很大的帮助。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Python数据结构之双向链表详解 - Python技术站

(0)
上一篇 2023年5月17日
下一篇 2023年5月17日

相关文章

  • C语言编程数据结构基础详解小白篇

    C语言编程数据结构基础详解小白篇攻略 1. 确定学习目标 在学习过程中,需要明确学习目标。对于小白来说,首先要了解C语言的基本语法,同时也需要掌握常用的数据结构。 2. 学习基本语法 2.1 变量和数据类型 C语言的变量必须先定义后使用 常用的数据类型包括整型、字符型、浮点型等 2.2 控制流程 C语言中常用的控制流程包括条件语句和循环语句 条件语句包括if…

    数据结构 2023年5月17日
    00
  • 一、对系统理论的认识

           经过一周的时间学习,我们知道了系统的定义:是一个由一组相互连接的要素构成的,能够实现某个目标的整体,任何一个系统都包括三种构成要件:要素连接,功能或目标。       1.系统的连接使得系统呈现特定的结构,使得系统的各个部件连接而产生系统特有的功能—相关性导新功能涌现。连接的媒介—“三流”(信息流,能量流,物质流)。       2.系统的静态…

    算法与数据结构 2023年4月18日
    00
  • C语言超详细讲解数据结构中的线性表

    C语言超详细讲解数据结构中的线性表完整攻略 线性表的概念和基本操作 线性表是指由同类型的数据元素构成的有限序列。即每个数据元素只有一个前驱和一个后继。线性表通常用于表示一维数组、列表、队列等数据结构。 线性表的基本操作包括: 初始化操作:创建一个空的线性表。 插入操作:在线性表中插入一个元素。 删除操作:删除线性表中的一个元素。 查找操作:查找线性表中是否存…

    数据结构 2023年5月17日
    00
  • C语言数据结构之队列的定义与实现

    C语言数据结构之队列的定义与实现 什么是队列 队列是一种特殊的线性数据结构,它只允许在队列的头部进行删除操作,在队列的尾部进行插入操作,这种操作方式被成为“先进先出”或“FIFO(first in first out)”。 队列的实现方式 队列可以通过数组和链表两种方式进行实现。 1. 数组实现 数组实现队列时,可以定义一个存放元素的数组,同时需要记录队列的…

    数据结构 2023年5月17日
    00
  • C语言线性表之双链表详解

    C语言线性表之双链表详解 前言 本教程将详细介绍C语言中双链表的实现方法以及相关操作,适合有一定C语言基础的读者。 双链表定义 双链表是一种常见的数据结构,与单链表不同,双链表中每个节点不仅有指向后续节点的指针,还有指向前续节点的指针,即“双向链表”。 双链表的节点结构体可以定义如下: typedef struct double_node{ int data…

    数据结构 2023年5月17日
    00
  • Java数据结构之最小堆和最大堆的原理及实现详解

    Java数据结构之最小堆和最大堆的原理及实现详解 什么是堆? 堆是一种特殊的树形数据结构,它满足以下两个条件: 堆是一个完全二叉树,即除了最后一层,其他层都必须填满,最后一层从左到右填满 堆中每个节点的值必须满足某种特定的条件,例如最小堆要求每个节点的值都小于等于其子节点的值。 堆一般分为两种类型:最小堆和最大堆。 最小堆:每个节点的值都小于等于其子节点的值…

    数据结构 2023年5月17日
    00
  • C++ 数据结构之布隆过滤器

    C++ 数据结构之布隆过滤器 简介 布隆过滤器是一种用于快速判断一个元素是否存在于一个集合中的数据结构。它的空间效率和查询效率都比较高,在某些场景下,它可以代替传统的哈希表。 原理 布隆过滤器的基本原理是:将一个元素映射为多个位数组中的位置。在插入元素时,将这些位置上的值设置为1;在查询元素时,如果这些位置上的值都为1,则认为元素存在于集合中;否则认为元素不…

    数据结构 2023年5月17日
    00
  • Java 数据结构链表操作实现代码

    下面是关于“Java 数据结构链表操作实现代码”的完整攻略。 1.链表实现原理 链表是一种经典的数据结构,其主要原理是通过指针将一系列节点连接起来。链表中的节点包含两个部分,一个是数据域,用于存放数据;另一个是指针域,用于指向下一个节点的位置。链表的头结点指向链表的第一个节点,最后一个节点的指针指向空。 2.链表的基本操作 链表的基本操作包括创建链表、插入节…

    数据结构 2023年5月17日
    00
合作推广
合作推广
分享本页
返回顶部