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++ 二叉树的实现超详细解析 在本篇文章中,我们将详细讲解如何使用C++语言实现二叉树数据结构。我们将分为以下几个部分: 二叉树的定义 二叉树的基本操作 C++实现 1. 二叉树的定义 二叉树是一种树形数据结构,其中每个节点最多有两个子节点。二叉树有以下几个特点: 树中的每个节点最多有两个子节点 左子节点的键值比父节点的键值小 右子节点的键值比父节点的键值…

    数据结构 2023年5月17日
    00
  • Java数据结构与算法之单链表深入理解

    Java数据结构与算法之单链表深入理解攻略 什么是单链表? 单链表(Singly Linked List)是指一个节点只指向下一个节点的链表。 单链表由多个节点组成,每个节点有两个属性:数据域和指针域。数据域保存节点的数据,指针域保存下一个节点的指针,因此每个节点包含两个域:data和next。 单链表的基本操作 单链表常用的基本操作包括: 在链表头部添加元…

    数据结构 2023年5月17日
    00
  • JavaScript树形数据结构处理

    对于“JavaScript树形数据结构处理”的完整攻略,我将从以下几个方面进行讲解: 树形数据结构的简介 树形数据结构在JavaScript中的表示 树形数据结构的处理方法 示例说明 树形数据结构的简介 树形数据结构,是一种常见的数据结构,由多个节点组成,每个节点有一个父节点和多个子节点。树形数据结构通常用来表示层级关系的数据。 树形数据结构在JavaScr…

    数据结构 2023年5月17日
    00
  • java数据结构与算法数组模拟队列示例详解

    下面是“java数据结构与算法数组模拟队列示例详解”的完整攻略。 标题 Java数据结构与算法:数组模拟队列示例详解 简介 本文将以Java语言为例,详细讲解如何使用数组模拟队列。对于初学者来说,队列是一个非常基础的数据结构,掌握其实现方法可以帮助进一步理解其他的数据结构和算法。 队列的定义 队列(Queue)是一种先进先出(First In First O…

    数据结构 2023年5月17日
    00
  • JS中的算法与数据结构之二叉查找树(Binary Sort Tree)实例详解

    JS中的算法与数据结构:二叉查找树(Binary Sort Tree) 什么是二叉查找树 二叉查找树(Binary Sort Tree),又称二叉搜索树或二叉排序树,是一种特殊的二叉树结构。它具有以下性质: 每个结点最多只有两个子结点。 左子树中的所有结点的值均小于它的根结点的值。 右子树中的所有结点的值均大于它的根结点的值。 没有相同节点值出现 因为具备以…

    数据结构 2023年5月17日
    00
  • C语言中数据结构之链式基数排序

    C语言中数据结构之链式基数排序 概述 链式基数排序是基数排序的一种实现方式。基数排序是一种桶排序算法,它通过将需要排序的数据分成多个桶,并且按照一定的顺序将数据从桶中取出来,以达到排序的目的。链式基数排序则使用了链表结构来实现桶的功能。 实现步骤 链式基数排序的实现步骤如下: 申请链表节点数组,并初始化链表头结点数组。链表的数量等于指定的基数,例如10进制的…

    数据结构 2023年5月17日
    00
  • C语言数据结构顺序表中的增删改(尾插尾删)教程示例详解

    C语言数据结构顺序表中的增删改(尾插尾删)教程示例详解 什么是顺序表 顺序表是一种线性表,它通过一块连续的存储空间来存储数据。顺序表中的数据元素排列在物理存储空间上也是连续的,每个元素占用一个固定的位置和大小,并且使用下标来访问。 顺序表的定义 下面是以int类型为例的一个简单顺序表的定义: #define SIZE 50 typedef struct { …

    数据结构 2023年5月17日
    00
  • 数据结构与算法之并查集(不相交集合)

    下面是详细的内容讲解。 数据结构与算法之并查集(不相交集合) 什么是并查集? 并查集,也叫不相交集合,是一种树形的数据结构,用于处理一些不相交集合(Disjoint Sets)的合并及查询问题。常常是在使用 Kruskal 算法或者 Prim 算法来求解最小生成树(Minimum Spanning Tree)时用到的一种数据结构。 并查集的基本操作 Make…

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