双链表(Doubly Linked List)是一种链式数据结构,与单链表类似,但每个节点包含两个指针,分别指向前一个节点和后一个节点。这样,双链表可以在两个方向上进行遍历,具有更高的灵活性。双链表通常包含以下内容:
-
节点结构:双链表的节点一般包含三部分:
- 数据域:存储数据或值。
- 前指针(prev):指向前一个节点。
- 后指针(next):指向下一个节点。
-
头节点和尾节点:双链表的头节点(head)是链表的起点,它的前指针为空(None);尾节点的后指针为空。
双链表的优点和缺点
优点
- 双向遍历:可以方便地向前和向后遍历链表。
- 删除操作更方便:在已知要删除的节点的情况下,不需要像单链表那样找前一个节点,直接使用双链表的前指针可以删除该节点。
缺点
- 占用更多空间:每个节点需要额外存储前指针,增加了内存消耗。
- 操作复杂度增加:插入和删除节点时需要维护前后指针,逻辑比单链表稍微复杂。
双链表的常用操作
- 初始化链表:创建头节点,初始化为空。
- 插入节点:
- 头插法:在链表头部插入新节点。
- 尾插法:在链表尾部插入新节点。
- 指定位置插入:在链表中的指定位置插入新节点。
- 删除节点:删除头节点、尾节点或指定节点,需维护相邻节点的指针。
- 查找节点:从头到尾或从尾到头遍历节点,找到目标值。
- 遍历链表:可以从头节点向尾部遍历,也可以从尾节点向头部遍历。
示例代码
以下是一个双链表的基本实现示例,用 Python 演示其基本操作:
class Node:
def __init__(self, data):
self.data = data # 数据域
self.prev = None # 前指针
self.next = None # 后指针
class DoublyLinkedList:
def __init__(self):
self.head = None
# 插入到链表头部
def insert_at_head(self, data):
new_node = Node(data)
new_node.next = self.head
if self.head is not None:
self.head.prev = new_node
self.head = new_node
# 插入到链表尾部
def insert_at_tail(self, data):
new_node = Node(data)
if self.head is None:
self.head = new_node
return
last = self.head
while last.next:
last = last.next
last.next = new_node
new_node.prev = last
# 删除指定节点
def delete_node(self, node):
if self.head is None or node is None:
return
if node == self.head:
self.head = node.next
if node.next:
node.next.prev = node.prev
if node.prev:
node.prev.next = node.next
# 打印链表
def print_list(self):
node = self.head
while node:
print(node.data, end=" ")
node = node.next
print()
# 测试双链表
dll = DoublyLinkedList()
dll.insert_at_head(1)
dll.insert_at_tail(2)
dll.insert_at_tail(3)
dll.print_list() # 输出: 1 2 3
dll.delete_node(dll.head.next) # 删除节点2
dll.print_list() # 输出: 1 3
用途
双链表常用于需要频繁插入、删除的场景,比如:
- LRU缓存:双链表配合哈希表可以实现快速的最近最少使用(LRU)缓存。
- 导航结构:在浏览器前进和后退页面的功能中,可以使用双链表记录历史页面,方便在两个方向上快速切换。