# 在单向链表中,每一个节点都是一个对象
# 节点类
class LNode:
def __init__(self, elem, next_=None):
self.elem = elem
self.next = next_
list1 = LNode(1)
p = list1
for i in range(2, 11):
p.next = LNode(i)
p = p.next
p = list1
while p is not None: # 可以直接写为while p
print(p.elem)
p = p.next
# 基于节点类LNode定义一个单链表对象的类
class LList:
def __init__(self, head):
self._head = None # _head是链表的头节点,因为_head域作为对象的内部表示,
# 不希望外部使用,所以习惯上用单个下划线开头
# _head作为判断表是否空的标志
def is_empty(self): # 判断是否为空
return self._head is None
def prepend(self, elem): # 在表头插入数据
self._head = LNode(elem, self._head)
def pop(self):
if self_head is None: # 删除表头结点,如果没有就引发异常
raise LinkedListUnderflow("in pop")
e = self._head.elem
self._head = self._head.next
return e
# 后端操作
# 在链表的最后插入元素
def append(self, elem):
if self._head is None:
self._head = LNode(elem)
return
p = self._head
while p.next:
p = p.next
p.next = LNode(elem)
# 删除链表最后的元素
def pop_last(self):
if self._head is Nono: # 那就说明是空表
raise LinkedListUnderflow("in pop_last")
p = self._head
if p.next == None: # 链表只有一个元素
e = self.elem
self._head = None
return e
while p.next.next is not None: # 直到p.next是最后的节点
p = p.next
e = p.next
p.next = None
return e
# 找到满足给定条件的表元素
def find(self, pred):
p = self._head
while p is not None:
if pred(p.elem):
return p.elem
p = p.next
# 查看被操作的表当时的情况
def printall(self):
p = self._head
while p:
print(p.elem, end=' ')
if p.next is not None:
print(',', end='')
p = p.next
print('')
# 迭代器的使用
# yield的使用非常关键,具体的用法可以百度
# 可以把yield看成是一个逐个输出的过程
def elements(self):
p = self._head
while p:
yield p.elem
p = p.next
# 调用迭代器
for i in list1.elements:
print(i)
# 筛选生成器:对所有满足条件的元素进行处理
# 也是生成器的一种
def filter(self, pred):
p = self._head
while p:
if pred(self):
yield p.elem
p = p.next
# 链表的使用
mlist = LList(1)
for i in range(10):
mlist.prepend(i)
for i in range(11, 20):
mlist.append(i)
mlist.printall()
循环单链表类
class LCList: # 循环单链表类
def __init__(self):
self._rear = None
def is_empty(self):
return self._rear is None
def prepend(self, elem): # 前端添加
p = LNode(elem)
if self._rear is None: # 如果是空的表
p.next = p
self._rear = p
else:
p.next = self._rear.next
self._rear.next = p
def append(self, elem): # 尾端添加
self.prepend(elem)
self._rear = self._rear.next
def pop(self): # 前端弹出
if self._rear is None:
raise LinkedListUnderflow("in pop of CLList")
p = self._rear.next
if self._rear is p:
self.rear = None
else:
self._rear.next = p.next
return p.elem
def printall(self): # 输出表元素
if self.is_empty():
return
p = self._rear.next
while True:
print(p)
if p is self._rear:
break
p = p.next
链表的两个特别的操作
反转
# 节点类
class LNode:
def __init__(self, elem, next_=None):
self.elem = elem
self.next = next_
# 链表的操作
# 链表反转
# 把链表想象成一摞书就可以了
def rev(self):
p = None
while self._head is not None:
q = self._head
self._head = q.next # 头节点往下移动
q.next = p
p = q # p是新表中的第一个元素
self._head = p # 重置新的表头链接
链表排序,
采用插入排序的思想
先通过列表看看基本思想
def list_sort(lst):
for i in range(1, len(lst)): # 默认[0:1]相当于已经排好了序
x = lst[i]
j = i
while j > 0 and lst[j-1] > x:
lst[j] = lst[j-1]
j -= 1
lst[j] = x
对于单链表使用插入排序有两种思路,一种是通过更换元素的大小进行,另外一种是调整各个节点的链接关系
考虑第一种,更换元素
def sort1(self):
if self._head is None:
return
crt = self._head.next
while crt is not None:
x = crt.elem
p = self._head
while p is not crt and p.elem <= x: # 逐个比较,跳过小的
p = p.next
while p is not crt:
y = p.elem
p.elem = x
x = y
p = p.next
crt.elem = x
crt = crt.next
考虑第二种,通过改变元素之间的链接
def sort(self):
p = self._head
if p is Noen or p.next is None:
return
rem = p.next
p.next = None
while rem is not None:
p = self._head
q = None
while p is not None and p.elem <= rem.elem:
q = p
p = p.next
if q = None:
self._head = rem
else:
q.next = rem
q = rem
rem = rem.next
q.next = p