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日

相关文章

  • Go语言数据结构之希尔排序示例详解

    Go语言数据结构之希尔排序示例详解 希尔排序简介 希尔排序,也称为缩小增量排序,是插入排序的一种更高效的改进版本;希尔排序是非稳定排序算法。 希尔排序的基本思想是已距离进行“减半”的插入排序;先将整个待排序的记录序列分割成若干个子序列,分别进行直接插入排序,待各子序列中的记录基本有序时,再将子序列合并为整体有序序列。 希尔排序的过程 从上面的简介中我们可以得…

    数据结构 2023年5月17日
    00
  • 基于python实现模拟数据结构模型

    实现一个模拟数据结构模型的过程需要考虑以下几个步骤: 确定数据结构类型,例如链表、栈、队列、二叉树等。 设计数据结构的具体实现方法,例如链表可采用节点、指针的方式实现,栈可以使用列表或数组实现,队列可使用循环队列实现等。 使用Python编写数据结构相关的类、方法、函数等,确保代码的可读性、灵活性和易维护性。 使用示例数据测试数据结构的各种操作,例如插入、删…

    数据结构 2023年5月17日
    00
  • C语言结构体详细图解分析

    针对C语言结构体详细图解分析的攻略,我来详细讲解一下。 一、什么是结构体? 结构体是C语言中一种自定义数据结构类型,是将不同类型的变量组合在一起的方式,形成了新的数据类型。结构体成员可以是任意类型的数据,包括基本类型、数组、指针、函数等,可以理解为一个包含多个变量的大变量。 二、结构体的定义和使用 定义结构体的方式为: struct name { type1…

    数据结构 2023年5月17日
    00
  • 一步步带你学习设计MySQL索引数据结构

    一步步带你学习设计MySQL索引数据结构 索引原理 在MySQL中,索引是一种数据结构,用于快速查找表中的记录。在一张表中,可以使用不同的列来创建索引,索引可以大大提高查询效率,减少扫描行数,加快数据查询速度。 索引的实现一般使用的是B树和B+树这两种数据结构,因为它们都具有良好的平衡性,可以快速查找,插入和删除。 如何设计MySQL索引 确认需要优化的查询…

    数据结构 2023年5月17日
    00
  • 举例讲解C语言程序中对二叉树数据结构的各种遍历方式

    那么我们先来介绍一下二叉树。 什么是二叉树? 二叉树是一种树状的数据结构,它的每个节点最多有两个子节点,分别称为左子节点和右子节点。二叉树节点的定义如下: typedef struct TreeNode { int val; TreeNode *left; TreeNode *right; TreeNode(int x) : val(x), left(NUL…

    数据结构 2023年5月17日
    00
  • Java数据结构之顺序表篇

    Java数据结构之顺序表篇 什么是顺序表 顺序表是由一组地址连续、大小相等的存储单元依次存储数据元素的线性表。 顺序表的表示 Java语言中,可以使用数组来表示顺序表。 public class SeqList<T> { private Object[] element;// 定义数组存储数据元素 private int length;// 当前…

    数据结构 2023年5月17日
    00
  • Go 数据结构之堆排序示例详解

    Go 数据结构之堆排序示例详解 什么是堆? 堆(Heap)是一种特殊的树形数据结构,它满足下列性质: 堆中每个节点的关键字都不大于(或不小于)其子节点的关键字。 堆中,根节点(顶端)是最小或最大元素。 堆实际上是一个完全二叉树,因此可以用数组实现。对于下标为i的节点,其左子节点为2i,右子节点为2i+1,父节点为i/2。 堆分为最大堆和最小堆。在最大堆中,父…

    数据结构 2023年5月17日
    00
  • Java数据结构之常见排序算法(下)

    Java数据结构之常见排序算法(下) 前言 这是 Java 数据结构之常见排序算法的第二篇,本篇文章将继续介绍常见的排序算法。对于尚未了解基本排序算法的读者,可以先阅读 Java 数据结构之常见排序算法(上)。 快速排序 快速排序是一种使用分治思想的排序算法,其思路是将一个数组分为两个子数组,再对子数组进行排序,这个过程不断递归执行。在具体实现时,选择一个元…

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