背景:
单循环链表是一种链表结构,其中最后一个节点指向第一个节点,从而形成一个环。
实现单循环链表通常涉及节点定义、插入节点、删除节点以及遍历链表等操作。以下是如何在Python中实现单循环链表的示例。
单循环链表的实现
1. 节点类
首先,定义链表的节点类,每个节点包含数据和指向下一个节点的指针。
class Node:def __init__(self, data):self.data = dataself.next = None
2. 单循环链表类
接下来,定义单循环链表类,包含插入、删除和遍历等方法。
class CircularLinkedList:def __init__(self):self.head = Nonedef insert(self, data):new_node = Node(data)if not self.head:self.head = new_nodeself.head.next = self.headelse:current = self.headwhile current.next != self.head:current = current.nextcurrent.next = new_nodenew_node.next = self.headdef delete(self, key):if self.head is None:returncurrent = self.headprev = Nonewhile True:if current.data == key:if prev:prev.next = current.nextelse:# Deleting the head nodeif current.next == self.head:self.head = Noneelse:tail = self.headwhile tail.next != self.head:tail = tail.nexttail.next = current.nextself.head = current.nextreturnprev = currentcurrent = current.nextif current == self.head:breakdef display(self):if self.head is None:print("List is empty")returncurrent = self.headwhile True:print(current.data, end=" -> ")current = current.nextif current == self.head:breakprint()# 示例使用
cll = CircularLinkedList()
cll.insert(1)
cll.insert(2)
cll.insert(3)
cll.display() # 输出: 1 -> 2 -> 3 -> cll.delete(2)
cll.display() # 输出: 1 -> 3 ->
代码解释
-
节点类 (Node):
__init__
: 初始化节点的数据和指向下一个节点的指针。
-
单循环链表类 (CircularLinkedList):
__init__
: 初始化链表的头指针。insert
: 在链表中插入新节点。- 如果链表为空,插入第一个节点并使其指向自己。
- 如果链表不为空,找到最后一个节点并将其
next
指针指向新节点,然后将新节点的next
指针指向头节点。
delete
: 删除包含指定数据的节点。- 如果链表为空,直接返回。
- 找到要删除的节点并更新前一个节点的
next
指针。 - 如果删除的是头节点,处理特殊情况,找到尾节点并更新其
next
指针指向新的头节点。
display
: 遍历并打印链表中的所有节点。
总结
单循环链表是一种方便的数据结构,适用于需要循环访问数据的场景。上面的代码展示了如何在Python中实现单循环链表的基本操作,包括插入、删除和遍历。
线性表和单链表都是常见的数据结构,用于存储和管理数据元素。它们有各自的特点和应用场景。下面详细介绍它们的概念、特点、优缺点,以及适用的场景。
线性表
概念
线性表(Linear List)是具有相同数据类型的 n 个元素的有限序列。在逻辑结构上,线性表中的数据元素具有线性关系,即每个元素有且只有一个前驱和一个后继(除第一个和最后一个元素外)。
特点
- 有序性:线性表中的元素按线性顺序排列。
- 唯一的前驱和后继:每个元素除了第一个元素没有前驱和最后一个元素没有后继外,其余元素都有唯一的前驱和后继。
- 长度可变:线性表的长度是可变的,可以动态增删元素。
实现方式
- 顺序存储结构(数组)
- 链式存储结构(链表)
单链表
概念
单链表(Singly Linked List)是一种链式存储结构,其中每个节点包含数据域和指向下一个节点的指针。链表中的最后一个节点的指针指向空(None),表示链表的结束。
特点
- 动态存储:不需要预先分配存储空间,可以动态地进行内存分配。
- 插入和删除操作高效:在已知位置进行插入和删除操作时,无需移动其他元素,只需改变指针指向。
- 顺序访问:只能从头节点开始顺序访问各节点,无法直接随机访问。
结构
- 节点:包含数据域(存储数据)和指针域(指向下一个节点)。
- 头指针:指向链表的第一个节点。
比较与对比
共同点
- 线性结构:线性表和单链表都属于线性结构,元素之间具有线性关系。
- 基本操作:都支持插入、删除、查找、更新、遍历等基本操作。
不同点
特点 | 线性表(顺序存储) | 单链表 |
---|---|---|
存储方式 | 数组 | 链表 |
内存分配 | 需预先分配连续空间 | 动态分配 |
随机访问 | 支持 | 不支持 |
插入和删除效率 | 低,需移动元素 | 高,只需修改指针 |
空间利用率 | 可能存在空间浪费 | 高效 |
实现难度 | 简单 | 较复杂 |
适用场景
-
线性表(数组):
- 适用于元素数量固定且变化不大的场景。
- 适用于需要频繁随机访问元素的场景。
- 适用于存储大小一致的数据(如基本数据类型)。
-
单链表:
- 适用于元素数量变化频繁的场景。
- 适用于插入和删除操作较多的场景。
- 适用于数据量较大且不确定的场景。
示例代码
顺序存储(数组实现)
class LinearList:def __init__(self):self.data = []def insert(self, index, element):if index < 0 or index > len(self.data):raise IndexError("Index out of bounds")self.data.insert(index, element)def delete(self, index):if index < 0 or index >= len(self.data):raise IndexError("Index out of bounds")return self.data.pop(index)def get(self, index):if index < 0 or index >= len(self.data):raise IndexError("Index out of bounds")return self.data[index]def update(self, index, element):if index < 0 or index >= len(self.data):raise IndexError("Index out of bounds")self.data[index] = elementdef length(self):return len(self.data)def display(self):print(self.data)# 示例使用
linear_list = LinearList()
linear_list.insert(0, 1)
linear_list.insert(1, 2)
linear_list.insert(2, 3)
linear_list.display() # 输出: [1, 2, 3]linear_list.update(1, 5)
linear_list.display() # 输出: [1, 5, 3]linear_list.delete(2)
linear_list.display() # 输出: [1, 5]print(linear_list.get(1)) # 输出: 5
print(linear_list.length()) # 输出: 2
单链表实现
class Node:def __init__(self, data):self.data = dataself.next = Noneclass LinkedList:def __init__(self):self.head = Nonedef insert(self, index, element):new_node = Node(element)if index == 0:new_node.next = self.headself.head = new_nodereturncurrent = self.headfor _ in range(index - 1):if current is None:raise IndexError("Index out of bounds")current = current.nextnew_node.next = current.nextcurrent.next = new_nodedef delete(self, index):if self.head is None:raise IndexError("Index out of bounds")if index == 0:self.head = self.head.nextreturncurrent = self.headfor _ in range(index - 1):if current.next is None:raise IndexError("Index out of bounds")current = current.nextif current.next is None:raise IndexError("Index out of bounds")current.next = current.next.nextdef get(self, index):current = self.headfor _ in range(index):if current is None:raise IndexError("Index out of bounds")current = current.nextif current is None:raise IndexError("Index out of bounds")return current.datadef update(self, index, element):current = self.headfor _ in range(index):if current is None:raise IndexError("Index out of bounds")current = current.nextif current is None:raise IndexError("Index out of bounds")current.data = elementdef length(self):count = 0current = self.headwhile current:count += 1current = current.nextreturn countdef display(self):current = self.headwhile current:print(current.data, end=" -> ")current = current.nextprint("None")# 示例使用
linked_list = LinkedList()
linked_list.insert(0, 1)
linked_list.insert(1, 2)
linked_list.insert(2, 3)
linked_list.display() # 输出: 1 -> 2 -> 3 -> Nonelinked_list.update(1, 5)
linked_list.display() # 输出: 1 -> 5 -> 3 -> Nonelinked_list.delete(2)
linked_list.display() # 输出: 1 -> 5 -> Noneprint(linked_list.get(1)) # 输出: 5
print(linked_list.length()) # 输出: 2
总结
线性表和单链表各有优缺点和适用场景。选择使用哪种数据结构,取决于具体的应用需求和操作频率。在需要频繁随机访问数据的场景下,线性表(数组)更为合适;在需要频繁插入和删除操作的场景下,单链表则更为高效。