如何实现一个链表?解释其插入和删除操作
链表是数据结构中的一个重要概念,它允许我们动态地存储一系列的元素。链表由一系列节点组成,每个节点至少包含两部分信息:一是存储的数据元素,二是指向下一个节点的引用。与数组不同,链表不需要预先分配固定大小的空间,因此它更加灵活,适用于动态添加或删除元素的情况。
一、链表的实现
在实现链表时,我们首先需要定义一个节点类(或结构体),用于存储数据和指向下一个节点的指针。然后,我们可以定义一个链表类,用于管理这些节点。
1. 节点类的定义
在Python中,我们可以这样定义节点类:
python复制代码
class ListNode: | |
def __init__(self, x): | |
self.val = x | |
self.next = None |
在这个定义中,ListNode
类有两个属性:val
用于存储节点的值,next
是一个指向下一个节点的指针。初始时,next
指向 None
,表示这是链表的末尾。
2. 链表类的定义
接下来,我们定义链表类:
python复制代码
class LinkedList: | |
def __init__(self): | |
self.head = None # 链表头节点 | |
def insert(self, val): | |
# 插入操作 | |
pass | |
def delete(self, val): | |
# 删除操作 | |
pass |
在这个定义中,LinkedList
类有一个属性 head
,表示链表的头节点。我们还预留了 insert
和 delete
方法的占位符,用于实现链表的插入和删除操作。
二、链表的插入操作
链表的插入操作可以分为在链表头部插入、在链表尾部插入和在链表中间插入三种情况。这里我们分别讨论这三种情况的实现。
1. 在链表头部插入
在链表头部插入元素是最简单的情况。我们只需要创建一个新节点,将其 next
指针指向当前的头节点,然后将链表的头指针指向新节点即可。
python复制代码
class LinkedList: | |
# ... 其他方法 ... | |
def insert_at_head(self, val): | |
new_node = ListNode(val) # 创建新节点 | |
new_node.next = self.head # 将新节点的 next 指向当前头节点 | |
self.head = new_node # 更新头节点为新节点 |
2. 在链表尾部插入
在链表尾部插入元素稍微复杂一些。我们需要遍历链表,找到最后一个节点,然后将新节点的 next
指针指向 None
,并将最后一个节点的 next
指针指向新节点。
python复制代码
class LinkedList: | |
# ... 其他方法 ... | |
def insert_at_tail(self, val): | |
new_node = ListNode(val) # 创建新节点 | |
if self.head is None: # 如果链表为空,则新节点为头节点 | |
self.head = new_node | |
else: | |
current = self.head # 从头节点开始遍历链表 | |
while current.next is not None: # 找到最后一个节点 | |
current = current.next | |
current.next = new_node # 将最后一个节点的 next 指向新节点 |
3. 在链表中间插入
在链表中间插入元素是最复杂的情况。我们需要先找到要插入位置的前一个节点,然后将新节点的 next
指针指向该位置的节点,再将前一个节点的 next
指针指向新节点。
python复制代码
class LinkedList: | |
# ... 其他方法 ... | |
def insert_at_index(self, index, val): | |
if index < 0: # 检查索引是否有效 | |
raise IndexError("Index out of range") | |
new_node = ListNode(val) # 创建新节点 | |
if index == 0: # 如果在头部插入,则调用 insert_at_head 方法 | |
self.insert_at_head(val) | |
else: | |
current = self.head # 从头节点开始遍历链表 | |
for _ in range(index - 1): # 找到要插入位置的前一个节点 | |
if current is None: # 如果链表长度小于 index,则抛出异常 | |
raise IndexError("Index out of range") | |
current = current.next | |
new_node.next = current.next # 将新节点的 next 指向当前位置的节点 | |
current.next = new_node # 将前一个节点的 next 指向新节点 |