Python3 实现单向链表
链表定义与简介
- 定义:链表与顺序表(Python中列表)性质相反,链表是物理单元上非顺序的、非连续的,在逻辑顺序上其数据元素是通过指针实现的,组成链表的每一个元素也可以叫做链表的节点,节点可以在运行时动态生成

单向链表中所有的元素也可以称之为节点,每个节点包含两个区域,如上图item区域称为数据域,next区域为指针域,单向链表中尾节点的判断只需判断该节点的指针(next)是否指向空即可。
链表(Linked list)与顺序表(Sequence list)的主要差异:
- 顺序表的内存地址是连续的,其数据元素有对应唯一的索引,搜索时非常方便,但进行元素插入时较麻烦,每次插入元素,其后所有元素都要移动一位。
- 而链表内存地址是非连续、非顺序的,逻辑顺序由指针实现,在插入元素时只需将指定位置的前一个元素的指针断开,并指向要插入的元素的节点,然后插入的元素指针再指向下一个节点即可,但是在查询元素时,需要从头结点开始一个一个遍历寻找。
由于链表不是必须按顺序存储,链表在插入的时候可以达到O(1)的复杂度,比线性表顺序表快得多,但是查找一个节点或者访问特定编号的节点则需要O(n)的时间,而线性表和顺序表相应的时间复杂度分别是O(logn)和O(1)。
定义单链表
# 定义节点
class Node:
def __init__(self, item):
self.item = item
self.next = None
# 定义链表
class SingleLinkList:
def __init__(self):
self._head = None
if __name__ == '__main__':
# 创建链表
link_list = SingleLinkList()
# 创建结点
node1 = Node(1)
node2 = Node(2)
# 将结点添加到链表
link_list._head = node1
# 将第一个结点的next指针指向下一结点
node1.next = node2
# 访问链表
print("head", link_list._head) # 访问第一个结点数据
print(link_list._head.item) # 访问第一个结点数据
print(link_list._head.next.item) # 访问第二个结点数据
一个简单的链表,没有增删改查等功能,操作十分不便
接下来对其,进行一部分常用功能实现:
- 清空元素clear(),断开头结点的指针,长度为0
- 展示元素的值show_items()
- 获取元素get_value_by_index(),以偏移量获取元素的值,超出偏移量会报错IndexErorr,可以是负偏移
- 判断链表是否为空is_empty()
- 返回链表长度length()
- 在指定位置插入insert(),当超过实际长度,在最后插入;当为负数倒序选择插入,负数的绝对值大于实际长度则在最前面插入
- 在末尾追加元素append()
- 指定偏移量移除元素remove(),超过偏移量,抛出IndexErorr,可以使用负偏移
- 判断一个元素是否存在于链表is_exist(),存在返回True,否则返回False
- 返回元素的偏移indexOf()
代码实现
class Node:
"""The nodes of single linked list"""
def __init__(self, item):
self.item = item
self.next = None
class SingleLinkedList:
def __init__(self):
"""Initialize the head and the length of single linked list"""
self.head = None
def clear(self):
"""CLear a linked list"""
self.head = None
def show_items(self):
"""Show all the elements of linked list"""
if self.is_empty():
return None
cur = self.head
while cur.next:
yield cur.item
cur = cur.next
yield cur.item
def get_value_by_index(self, index):
"""Get a value by index"""
node = self.head
index = self.length()+index if index < 0 else index
if index < 0:
raise IndexError('index out of range')
try:
for i in range(index):
node = node.next
return node.item
except AttributeError as e:
raise IndexError('index out of range')
def is_empty(self):
"""Judge if a linked list is empty"""
return self.head is None
def length(self):
"""Return the elements number of a linked list"""
cur = self.head
if not cur:
return 0
count = 1
while cur.next:
count += 1
cur = cur.next
return count
def insert(self, index, item):
"""Insert an element before the given index of a node"""
node = Node(item)
length = self.length()
# Empty list, append directly
if not self.head:
self.append(item)
if index < 0 and (index + length) >= 0:
index += length
# index>0
if index > 0:
cur = self.head
while cur.next:
if index <= 1:
break
cur = cur.next
index -= 1
node.next = cur.next
cur.next = node
elif index == 0 or index + length < 0:
temp = self.head
node.next = temp
self.head = node
def append(self, item):
"""Append elements to the end of a linked list"""
node = Node(item)
if self.is_empty():
self.head = node
else:
cur = self.head
while cur.next:
cur = cur.next
cur.next = node
def remove(self, index):
"""Remove an element by index"""
if not -self.length() - 1 < index < self.length():
raise IndexError('remove index out of range')
if index < 0:
index += self.length()
print(f"index", index)
if index == 0:
print("Get into ")
self.head = self.head.next
else:
cur = self.head
pre = cur
while index > 0:
pre = cur
cur = cur.next
index -= 1
pre.next = cur.next
def is_exist(self, item):
"""Judge if an element in linked-list"""
return item in self.show_items()
def indexOf(self, item):
"""Return a given item's index where is the first appearance in the list"""
return list(self.show_items()).index(item)
验证功能
if __name__ == '__main__':
SLL = SingleLinkedList()
print(f"If the linked list is empty?: {SLL.is_empty()}")
# Append elements to the end
for i in range(5):
SLL.append(i)
print(f"Show all items:{list(SLL.show_items())}")
print(f"The length of {SLL.__class__.__name__}: {SLL.length()}")
# _index>0
_index, _item = 9, 11
SLL.insert(_index, _item)
print(f"Insert {_item} before linked list[{_index}]: {list(SLL.show_items())}")
# _index=0
_index, _item = 0, 22
SLL.insert(_index, _item)
print(f"Insert {_item} before linked list[{_index}]: {list(SLL.show_items())}")
# _index<0 and length+_index>0
_index, _item = -3, 33
SLL.insert(_index, _item)
print(f"Insert {_item} before linked list[{_index}]: {list(SLL.show_items())}")
# _index<0 and length+_index<0
_index, _item = -21, 44
SLL.insert(_index, _item)
print(f"Insert {_item} before linked list[{_index}]: {list(SLL.show_items())}")
_index = -5
SLL.remove(_index)
print(f"Remove an element by index[{_index}]: {list(SLL.show_items())}")
# Get a value by index, if index out of range, throw a IndexError
_index = 3
print(f"Get a value by index[{_index}], its value: {SLL.get_value_by_index(3)}")
_item = 44
print(f"If item:[{_item}] in linked list {SLL.__class__.__name__}? {SLL.is_exist(_item)} ")
# CLear a linked list
print(f"The linked list has been cleared: {SLL.__class__.__name__}: {SLL.clear()}")
print(f"The length of {SLL.__class__.__name__}: {SLL.length()}")
结果
If the linked list is empty?: True
Show all items:[0, 1, 2, 3, 4]
The length of SingleLinkedList: 5
Insert 11 before linked list[9]: [0, 1, 2, 3, 4, 11]
Insert 22 before linked list[0]: [22, 0, 1, 2, 3, 4, 11]
Insert 33 before linked list[-3]: [22, 0, 1, 2, 33, 3, 4, 11]
Insert 44 before linked list[-21]: [44, 22, 0, 1, 2, 33, 3, 4, 11]
Remove an element by index[-5]: [44, 22, 0, 1, 33, 3, 4, 11]
Get a value by index[3], its value: 1
If item:[44] in linked list SingleLinkedList? True
The linked list has been cleared: SingleLinkedList: None
The length of SingleLinkedList: 0
本文详细介绍Python中单向链表的数据结构实现,包括节点定义、链表操作及增删改查等常用功能,对比链表与顺序表的特性。
2730

被折叠的 条评论
为什么被折叠?



