数据结构之单链表

文章目录

数据结构中的单链表是一种线性数据结构,其核心特点是通过链式存储的方式来管理一组具有线性关系的数据元素。单链表中的每个元素称为节点(Node),每个节点包含两部分:数据域(Data Field)和指针域(Pointer Field)。数据域用于存储实际数据,而指针域则存储指向下一个节点的指针(或称为链接)。单链表的最后一个节点的指针域通常设置为 nullnullptr,以标识链表的末端。

以下是对单链表的深入剖析:

基本概念与结构

节点(Node):单链表的基本组成单元,包含两部分:

  • 数据域(Data Field):存储数据元素的值,可以是任何类型(整数、浮点数、字符串、自定义结构体等)。
  • 指针域(Pointer Field) :存储指向下一个节点的指针,通常命名为 next。对于链表的最后一个节点,其指针域值为 null,表示链表在此结束。

链表(Linked List):由若干节点通过指针域相互连接形成的线性结构。链表可以为空,即没有任何节点;也可以有一个或多个节点。链表的表示通常包含一个指向首节点(头节点)的指针。

链表操作

插入:在链表的特定位置(头部、中间、尾部)创建新节点并将其链接到链表中。插入操作通常涉及更新新节点和其前驱节点的指针域。

删除:从链表中移除指定位置的节点。删除操作需要更新被删除节点的前驱节点的指针域,使其指向被删除节点的后继节点,并释放被删除节点的内存。

遍历:从头节点开始,沿着每个节点的指针域依次访问链表中的所有节点。遍历是实现链表查询、排序、搜索等操作的基础。

查找:在链表中查找特定值的节点。查找操作通常从头节点开始,逐个比较节点的数据域与目标值,直到找到匹配的节点或遍历完链表。

链表的种类

根据链表的结构和操作特性,单链表可以分为以下几种类型:

普通单链表:无附加特殊性质的单链表,仅支持基本的插入、删除、查找等操作。

带头节点的单链表:在链表的起始处增加一个特殊节点(头节点),其数据域可以为空或存储特定信息(如链表长度等),头节点的指针域指向第一个有效数据节点。这种结构便于处理空链表和在头部进行插入操作。

循环单链表 :与普通单链表不同,循环单链表的最后一个节点的指针域不再指向 null,而是指向头节点,形成一个环状结构。这种链表适合需要频繁遍历到链表尾部后立即回到头部的场景。

链表的特点与优缺点

特点

  • 动态性:链表的长度可以在程序运行时动态增长或缩短,无需预先设定固定大小。
  • 物理存储不连续:节点在内存中可以分散存储,每个节点只需要知道其后继节点的地址即可。
  • 插入、删除效率:在已知位置插入或删除节点的时间复杂度为 O(1),但在未知位置需要遍历查找,时间复杂度为 O(n)。

优点

  • 灵活的内存管理:链表能够高效地利用内存空间,无需预先分配大块连续内存。
  • 易于扩展:链表长度可动态变化,无需预先知道数据规模。

缺点

  • 额外的空间开销:每个节点都需要额外存储一个指针,占用额外内存。
  • 访问效率:随机访问节点的时间复杂度为 O(n),不如数组的随机访问速度快。
  • 内存碎片:长期增删可能导致内存空间碎片化。

应用举例

单链表广泛应用于各种编程场景,如:

  • 实现堆栈、队列等抽象数据类型。
  • 字符串处理,如实现动态字符串。
  • 图形/图像处理中的轮廓跟踪、边界表示等。
  • 数据库索引结构,如B树、B+树等的内部节点结构。

总之,单链表作为一种基础且灵活的数据结构,通过节点间的链式连接实现了对数据的高效管理。理解其结构、操作原理及优缺点,有助于在实际编程中根据需求选择合适的数据结构来解决问题。

以下是单链表在实际编程中的一些应用例子:

1. 实现堆栈(Stack)

堆栈是一种后进先出(LIFO)的数据结构,可以用单链表来实现。将链表的头节点视为堆栈顶(top),每次入栈(push)操作就是在链表头部插入新节点,出栈(pop)操作则是删除头节点并返回其数据。由于单链表支持在头部快速插入和删除节点,因此非常适合实现堆栈。

python 复制代码
class StackNode:
    def __init__(self, data):
        self.data = data
        self.next = None

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

    def push(self, data):
        new_node = StackNode(data)
        new_node.next = self.head
        self.head = new_node

    def pop(self):
        if not self.is_empty():
            popped_node = self.head
            self.head = self.head.next
            return popped_node.data
        else:
            raise Exception("Stack is empty")

    def is_empty(self):
        return self.head is None

2. 实现队列(Queue)

队列是一种先进先出(FIFO)的数据结构,可以使用带头节点的单链表来实现。将头节点的下一个节点视为队列头(front),尾节点作为队列尾(rear)。入队(enqueue)操作在尾部插入新节点,出队(dequeue)操作删除队列头节点。虽然单链表在尾部插入节点的效率较低,但通过维护一个指向尾节点的指针(称为尾指针),可以将入队操作的时间复杂度降低到 O(1)。

python 复制代码
class QueueNode:
    def __init__(self, data):
        self.data = data
        self.next = None

class LinkedListQueue:
    def __init__(self):
        self.head = QueueNode(None)  # 带头节点
        self.tail = self.head  # 尾指针初始指向头节点

    def enqueue(self, data):
        new_node = QueueNode(data)
        self.tail.next = new_node
        self.tail = new_node

    def dequeue(self):
        if not self.is_empty():
            dequeued_node = self.head.next
            self.head.next = dequeued_node.next
            if self.head.next is None:  # 更新尾指针,防止悬挂
                self.tail = self.head
            return dequeued_node.data
        else:
            raise Exception("Queue is empty")

    def is_empty(self):
        return self.head.next is None

3. 实现动态字符串(String)

动态字符串需要支持字符的高效插入、删除和查找。可以使用单链表来存储字符串的字符序列,每个节点存储一个字符。插入和删除字符时只需调整相应位置的节点指针,查找字符时需遍历链表。虽然链表的查找效率较低,但对于频繁插入和删除操作的动态字符串而言,其优势在于不需要频繁移动大量字符数据。

python 复制代码
class CharNode:
    def __init__(self, char):
        self.char = char
        self.next = None

class DynamicString:
    def __init__(self, initial_str=""):
        self.head = None
        for char in initial_str:
            self.append(char)

    def append(self, char):
        new_node = CharNode(char)
        if self.head is None:
            self.head = new_node
        else:
            current = self.head
            while current.next:
                current = current.next
            current.next = new_node

    # ...其他方法如 insert, delete, find, etc.

以上例子展示了单链表在实现堆栈、队列和动态字符串等数据结构中的应用。实际上,单链表还能应用于许多其他场景,如图算法、数据库索引、事件处理等,只要需要灵活管理线性数据且对插入、删除操作有较高要求的场合,单链表往往都能发挥重要作用。

python推荐学习汇总连接:
50个开发必备的Python经典脚本(1-10)

50个开发必备的Python经典脚本(11-20)

50个开发必备的Python经典脚本(21-30)

50个开发必备的Python经典脚本(31-40)

50个开发必备的Python经典脚本(41-50)


​最后我们放松一下眼睛

相关推荐
李元豪2 小时前
【智鹿空间】c++实现了一个简单的链表数据结构 MyList,其中包含基本的 Get 和 Modify 操作,
数据结构·c++·链表
我不是星海2 小时前
1.集合体系补充(1)
java·数据结构
Darkwanderor6 小时前
用数组实现小根堆
c语言·数据结构·二叉树·
鬣主任7 小时前
LinkedList和单双链表。
数据结构·链表
titan TV man7 小时前
上海市计算机学会竞赛平台2024年11月月赛丙组线段数
数据结构·算法
敲上瘾8 小时前
C++11新特性(二)
java·c语言·开发语言·数据结构·c++·python·aigc
知星小度S9 小时前
数据结构——排序
c语言·数据结构·算法
labuladuo5209 小时前
洛谷 P1725 琪露诺(线段树优化dp)
数据结构·算法·动态规划
曙曙学编程10 小时前
初级数据结构——顺序表
数据结构
Bucai_不才10 小时前
【数据结构】线性表——链表
数据结构·链表