链表反转和链表排序是两种链表的基本操作,在python里list类型的reverse()方法就是对list的反转,sort()方法可以对list的元素进行排序,本文将探讨这两种链表操作基于单链表的实现方式。
链表反转
对于单链表而言,链表反转可以有两种实现方式,一种是在节点之间搬动元素,即往复地将尾部元素搬到头部;另一种是修改节点的连接关系,通过改变节点的连接顺序来改表元素的顺序。但是单链表不支持从尾部向前查找元素,如果采用搬动元素的方法,则效率很低()。因此考虑第二种实现方式。注意到在链表头部插入节点或删除节点花费的时间都是O(1),如果不断从链表的头部取下节点,插入到另一个链表的头部,这样最后得到的就是反转后的链表,并且这是一个高效的操作,花费时间为O(n)。
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 #反转后的节点序列已经做好,重置表头连接
在实际生活中也经常能见到类似的过程,如通过调度把一列火车车厢的顺序顛倒过来。另外,如果桌上有一摞书,一本本拿下来放到另一处,叠成另一摞,也是这个操作的实例。
链表排序
排序算法有很多种,本结主要讨论基于插入排序的链表排序,插入排序的原理大家可以自行查找,这里不再赘述。主要实现有两种方式:1.基于移动元素的链表排序,2.基于调整链表的链表排序。
-
基于移动元素的链表排序
如图a)所示,在第i个节点d之前的链表节点元素都是已排序的,现在要将d插入前面的有序序列中。采用移动元素的方法,从头结点开始扫描该有序序列直到找到第一个大于d的节点位置,记为j。然后将j及j之后的元素依次后移,最后将d插入到j的位置。如此循环取出链表的元素做此操作,即可完成链表的排序。
#基于移动元素的链表排序
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 sort2(self):
p=self._head
if p is None 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 is None:
self._head=rem #rem是最小的,头部插入
else:
q.next=rem #q和p中间插入
q=rem
rem=rem.next
q.next=p