链表
链表是一种在存储单元上非连续、非顺序的存储结构。数据元素的逻辑顺序是通过链表中的指针链接次序实现。链表是由一系列的结点组成,结点可以在运行时动态生成。每个结点包含两部分:数据域与指针域。数据域存储数据元素,指针域存储下一结点的指针。
资料来源:https://zhuanlan.zhihu.com/p/60057180
单向链表
它的每个节点包含两个域,一个信息域(元素域)和一个链接域。这个链接指向链表中的下一个节点,而最后一个节点的链接域则指向一个空值。
由图可知:
head
保存首地址,item
存储数据,next
指向下一结点地址。
链表的优缺点:
- 链表失去了序列的随机读取优点,同时链表增加了指针域,空间开销也较大。
- 但它对存储空间的使用要相对灵活。
- 优势示例:
- 列如:有一堆数据[1,2,3,5,6,7],要在3和5之间插入4, 如果用数组,需要将5之后的数据都往后退一位,然后再插入4,这样非常麻烦,但是如果用链表,我就直接在3和5之间插入4就行。
定义节点
结点的数据结构为数据元素(item)与 指针(next)
class Node(object):
"""单链表的结点"""
def __init__(self, item):
# item存放数据元素
self.item = item
# next是下一个节点的标识
self.next = None
定义链表
链表需要具有首地址指针head。
class SingleLinkList(object):
"""单链表"""
def __init__(self):
self._head = None
示例:创建链表
class Node(object):
"""单链表的结点"""
def __init__(self, item):
# item存放数据元素
self.item = item
# next是下一个节点的标识
self.next = None
class SingleLinkList(object):
"""单链表"""
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(link_list._head.item) # 访问第一个结点数据 输出:1
print(link_list._head.next.item) # 访问第二个结点数据 输出:2
在链表中添加操作方法(增删改查)
主要实现功能如下:
is_empty()
链表是否为空length()
链表长度items()
获取链表数据迭代器add(item)
链表头部添加元素addend(item)
链表尾部添加元素insert(pos,item)
指定位置添加元素remove(item)
删除节点find(item)
查找节点是否存在
代码如下:
class Node(object):
"""单链表的结点"""
def __init__(self, item):
# item存放数据元素
self.item = item
# next是下一个节点的标识
self.next = None
class SingleLinkList(object):
"""单链表"""
def __init__(self):
self.head = None
def is_empty(self):
"""判断链表是否为空"""
return self.head is None
def length(self):
"""链表长度"""
# 初始指针指向head
cur = self.head
count = 0
# 指针指向None 表示到达尾部
while cur is not None:
count += 1
# 指针下移
cur = cur.next
return count
def items(self):
"""遍历链表"""
# 获取head指针
cur = self.head
# 循环遍历
while cur is not None:
# 返回生成器
yield cur.item
# 指针下移
cur = cur.next
def add(self, item):
"""向链表头部添加元素"""
node = Node(item)
# 新结点指针指向原头部结点
node.next = self.head
# 头部结点指针修改为新结点
self.head = node
def append(self, item):
"""尾部添加元素"""
node = Node(item)
# 先判断是否为空链表
if self.is_empty():
# 空链表,head 指向新结点
self.head = node
else:
# 不是空链表,则找到尾部,将尾部next结点指向新结点
cur = self.head
while cur.next is not None:
cur = cur.next
cur.next = node
def insert(self, index, item):
"""指定位置插入元素"""
# 指定位置在第一个元素之前,在头部插入
if index <= 0:
self.add(item)
# 指定位置超过尾部,在尾部插入
elif index > (self.length() - 1):
self.append(item)
else:
# 创建元素结点
node = Node(item)
cur = self.head
# 循环到需要插入的位置
for i in range(index - 1):
cur = cur.next
node.next = cur.next
cur.next = node
def remove(self, item):
"""删除节点"""
cur = self.head
pre = None
while cur is not None:
# 找到指定元素
if cur.item == item:
# 如果第一个就是删除的节点
if not pre:
# 将头指针指向头节点的后一个节点
self.head = cur.next
else:
# 将删除位置前一个节点的next指向删除位置的后一个节点
pre.next = cur.next
return True
else:
# 继续按链表后移节点
pre = cur
cur = cur.next
def find(self, item):
"""查找元素是否存在"""
return item in self.items()
if __name__ == '__main__':
link_list = SingleLinkList()
# 向链表尾部添加数据
for i in range(5):
link_list.append(i)
# 向头部添加数据
link_list.add(6)
# 遍历链表数据
for i in link_list.items():
print(i, end='\t')
# 链表数据插入数据
link_list.insert(3, 9)
print('\n', list(link_list.items()))
# 删除链表数据
link_list.remove(0)
# 查找链表数据
print(link_list.find(4))
输出结果:
6 0 1 2 3 4
[6, 0, 1, 9, 2, 3, 4]
True
循环链表
单向循环链表为单向链表的变种,链表的最后一个next指向链表头,新增一个循环。
循环链表定义
class Node(object):
"""单链表的结点"""
def __init__(self, item):
# item存放数据元素
self.item = item
# next是下一个节点的标识
self.next = None
class SingleCycleLinkList(object):
"""循环链表"""
def __init__(self):
self.head = None
def is_empty(self):
"""判断链表是否为空"""
return self.head is None
def length(self):
"""链表长度"""
# 链表为空
if self.is_empty():
return 0
# 链表不为空
count = 1
cur = self.head
while cur.next != self.head:
count += 1
# 指针下移
cur = cur.next
return count
def items(self):
""" 遍历链表 """
# 链表为空
if self.is_empty():
return
# 链表不为空
cur = self.head
while cur.next != self.head:
yield cur.item
cur = cur.next
yield cur.item
def add(self, item):
""" 头部添加结点"""
node = Node(item)
if self.is_empty(): # 为空
self.head = node
node.next = self.head
else:
# 添加结点指向head
node.next = self.head
cur = self.head
# 移动结点,将末尾的结点指向node
while cur.next != self.head:
cur = cur.next
cur.next = node
# 修改 head 指向新结点
self.head = node
def append(self, item):
"""尾部添加结点"""
node = Node(item)
if self.is_empty(): # 为空
self.head = node
node.next = self.head
else:
# 寻找尾部
cur = self.head
while cur.next != self.head:
cur = cur.next
# 尾部指针指向新结点
cur.next = node
# 新结点指针指向head
node.next = self.head
def insert(self, index, item):
""" 指定位置添加结点"""
if index <= 0: # 指定位置小于等于0,头部添加
self.add(item)
# 指定位置大于链表长度,尾部添加
elif index > self.length() - 1:
self.append(item)
else:
node = Node(item)
cur = self.head
# 移动到添加结点位置
for i in range(index - 1):
cur = cur.next
# 新结点指针指向旧结点
node.next = cur.next
# 旧结点指针 指向 新结点
cur.next = node
def remove(self, item):
""" 删除一个结点 """
if self.is_empty():
return
cur = self.head
pre = Node
# 第一个元素为需要删除的元素
if cur.item == item:
# 链表不止一个元素
if cur.next != self.head:
while cur.next != self.head:
cur = cur.next
# 尾结点指向 头部结点的下一结点
cur.next = self.head.next
# 调整头部结点
self.head = self.head.next
else:
# 只有一个元素
self.head = None
else:
# 不是第一个元素
pre = self.head
while cur.next != self.head:
if cur.item == item:
# 删除
pre.next = cur.next
return True
else:
pre = cur # 记录前一个指针
cur = cur.next # 调整指针位置
# 当删除元素在末尾
if cur.item == item:
pre.next = self.head
return True
def find(self, item):
""" 查找元素是否存在"""
return item in self.items()
if __name__ == '__main__':
link_list = SingleCycleLinkList()
print(link_list.is_empty())
# 头部添加元素
for i in range(5):
link_list.add(i)
print(list(link_list.items()))
# 尾部添加元素
for i in range(6):
link_list.append(i)
print(list(link_list.items()))
# 添加元素
link_list.insert(3, 45)
print(list(link_list.items()))
# 删除元素
link_list.remove(5)
print(list(link_list.items()))
# 元素是否存在
print(4 in link_list.items())