探索单链表数据结构:理解与实现
🍋引言
在计算机科学和数据结构中,链表是一种基本且重要的数据结构,用于存储和组织数据。单链表是其中最简单的一种形式,它由一系列节点组成,每个节点都包含一个数据元素和一个指向下一个节点的指针。在这篇博客中,我们将深入探讨单链表的工作原理以及如何用代码实现它。
最近在刷力扣的时候,发现链表这块挺重要的,所以来回忆回忆
🍋什么是单链表?
单链表是一种线性数据结构,其中的节点按照线性顺序排列。每个节点都包含两个部分:
- 数据元素:存储实际的数据。
- 指针(或引用):指向下一个节点的位置。
这个简单的结构允许我们在链表中添加、删除和访问元素,而不需要像数组一样具有固定的大小。这使得链表在需要频繁插入和删除元素时非常有用。
🍋单链表的基本操作
- 插入操作
要在单链表中插入一个新的节点,我们需要执行以下步骤:
- 创建一个新的节点,并将要插入的数据存储在其中。
- 将新节点的指针指向原链表中的下一个节点。
- 更新前一个节点的指针,使其指向新节点。
- 删除操作
要删除链表中的节点,我们需要执行以下步骤:
- 找到要删除的节点的前一个节点。
- 更新前一个节点的指针,使其跳过要删除的节点,直接指向后一个节点。
- 访问操作
- 要访问链表中的节点,我们可以从链表的头节点开始,依次遍历每个节点,直到找到目标节点或到达链表的末尾。
🍋单链表的实现
# 创建一个节点类(Node),用于表示单链表的节点
class Node:
def __init__(self, data):
self.data = data # 存储节点的数据
self.next = None # 存储指向下一个节点的指针,默认为None
# 创建一个单链表类(LinkedList)
class LinkedList:
def __init__(self):
self.head = None # 初始化链表,头节点默认为None
# 向链表中添加元素的方法
def append(self, data):
new_node = Node(data) # 创建一个新的节点,将数据存储在其中
if not self.head: # 如果链表为空,将新节点设置为头节点
self.head = new_node
return
current = self.head # 从头节点开始遍历链表
while current.next: # 移动到链表的末尾
current = current.next
current.next = new_node # 将新节点连接到链表的末尾
# 显示链表内容的方法
def display(self):
current = self.head # 从头节点开始遍历链表
while current: # 遍历整个链表
print(current.data, end=" -> ") # 打印当前节点的数据
current = current.next # 移动到下一个节点
print("None") # 链表结束后打印 "None" 表示结束
# 创建一个新的链表实例
my_linked_list = LinkedList()
# 向链表中添加元素
my_linked_list.append(1)
my_linked_list.append(2)
my_linked_list.append(3)
# 显示链表的内容
my_linked_list.display()
上述代码首先定义了两个类:Node 和 LinkedList。Node 类表示链表中的节点,每个节点包含一个数据元素和一个指向下一个节点的指针。LinkedList 类表示单链表,其中包含一个头节点,通过头节点可以访问整个链表。
在 LinkedList 类中,有两个主要方法:
- append(data) 方法用于向链表中添加新的节点。它会创建一个新的节点并将其连接到链表的末尾。
- display() 方法用于显示链表的内容。它会从头节点开始遍历链表,并打印每个节点的数据,直到链表结束。
最后,创建了一个 my_linked_list 实例,向链表中添加了三个元素(1、2 和 3),然后调用 display() 方法来显示链表的内容。
运行结果如下
🍋练习题
这里我们选一道我考研时期做过的题
题目:设计一个递归算法,删除不带头结点的单链表L中所有值为x的结点
首先我们要明确这题的几种可能,尤为重要的是为空的可能,我记得我之前总是遗忘
- 如果链表为空,递归结束。
- 如果链表的头结点的值等于 x,则将头结点删除,并递归调用删除函数来处理剩余的链表(即调用函数自身)。
- 如果链表的头结点的值不等于 x,则保留头结点,并递归调用删除函数来处理剩余的链表。
class ListNode:
def __init__(self, value):
self.value = value
self.next = None
def delete_nodes_with_value(head, x):
# 递归终止条件:如果链表为空,直接返回
if not head:
return None
# 递归处理剩余的链表
head.next = delete_nodes_with_value(head.next, x)
# 如果当前节点的值等于 x,则返回下一个节点,相当于删除了当前节点
if head.value == x:
return head.next
return head
def print_linked_list(head):
current = head
while current:
print(current.value, end=" -> ")
current = current.next
print("None")
# 创建一个示例链表:1 -> 2 -> 3 -> 2 -> 4
node1 = ListNode(1)
node2 = ListNode(2)
node3 = ListNode(3)
node4 = ListNode(2)
node5 = ListNode(4)
node1.next = node2
node2.next = node3
node3.next = node4
node4.next = node5
print("原始链表:")
print_linked_list(node1)
x = 2
new_head = delete_nodes_with_value(node1, x)
print(f"删除值为 {x} 的节点后的链表:")
print_linked_list(new_head)
首先,我们定义了一个节点类 ListNode,该类用于表示链表的节点。每个节点有两个属性:value 用于存储节点的值,next 用于指向下一个节点。
接下来,我们定义了一个递归函数 delete_nodes_with_value(head, x),它接受链表的头节点 head 和要删除的值 x 作为参数。这个函数执行以下操作:
- 首先,它检查递归的终止条件。如果链表为空(head 为 None),则递归结束,返回 None。
- 否则,它递归调用自己,传递链表的下一个节点 head.next,以处理剩余的链表部分。
- 在递归回溯时,它检查当前节点的值是否等于 x。如果相等,它将返回下一个节点 head.next,这相当于删除了当前节点。
- 如果当前节点的值不等于 x,它将返回当前节点 head,保留当前节点,并继续处理下一个节点。
接下来,我们定义了一个辅助函数 print_linked_list(head),用于打印链表的内容,以便在删除操作后验证链表的状态。
🍋总结
单链表是一个非常有用的数据结构,用于处理各种编程问题,包括数据存储、算法实现和数据检索。希望这个解释有助于你理解如何实现和使用单链表。
挑战与创造都是很痛苦的,但是很充实。
- 点赞
- 收藏
- 关注作者
评论(0)