概念介绍
上一博文已经介绍了Python实现单向无序链表的实现方式,这篇博文来介绍Python如何实现单向有序链表。有序和无序仅仅指节点所包含的数据成员的大小排列顺序,有序指各个节点按照节点数据成员的大小顺序排序,从大到小或从小到大。无序则可以任意排列。
链表节点实现
实现方式完全同单向无序列表,这里不再过多介绍,感兴趣的可以看Python实现单向无序链表(Singly linked list)关于节点的实现方式。
链表实现
链表的实现中,链表初始化,判断是否为空,获取链表长度与无序链表一致。同时,remove方式的实现也相同,都是遍历链表,找到指定节点,然后删除。主要的区别在于查找和添加(search和add方法)有所区别。
在无序链表中,查找是依次遍历各个节点,直至找到该节点,若节点不存在于链表中,也会一直遍历直到链表尾部。对于有序链表来说,由于各个节点的数据成员是有大小排序的,则查找算法可以有所优化。假如有这样一个有序链表,链表中各个节点的数据依次为17,26,31, 54,77,93。是按从小到大的顺序依次排序。如果我们想查找节点数据成员为45的节点是否在链表中,当我们找到31所在的节点时,其下一个节点数据类型为54,而45正好在31和54之间,却没有在链表中找到,则45所在的节点不存在,且不需要再继续遍历链表,因为随后的节点数据成员都比54要大。如下图所示。
下面来实现其算法,依然是遍历各个节点,若找到则返回True,若当前节点的数据成员值>item,则为找到,不需要继续遍历后续节点,因为后续节点的值比当前节点的值还要大。
若当前节点的值<item,则继续遍历。若链表为空或找到链表尾部依然没找到,则直接返回False。
def search(self, item):
current = self.head
while current is not None:
if current.get_data() == item:
return True
if current.get_data() > item:
return False
else:
current = current.get_next()
return False
接下来实现有序链表的add(添加新节点)方法。注意,在无序列表中,新添加的节点成为了链首节点,这种实现方式很简单。但在有序链表中,添加方法必须在插入链表后,依然要保持整个链表的有序状态(从大到小或从小到大)。假如有这样一个链表,节点的大小顺序为17,26,54, 77,93,我们想将31添加到链表中,显然应该添加到26和54中间的位置。
下面介绍实现原理:首先要插入节点,必然有一个当前节点和上一个节点,分别用current和previous指代。最后的目的是将指定节点插入到当前节点和上一个节点中间。
首先遍历节点,若当前节点的值大于指定节点的值,而显然后续的节点值比当前节点的值更大,则链表终止遍历。指定节点的值显然在当前节点和上一节点之间。若当前节点的值比指定节点的值小,则继续遍历,直至到最后一个节点。最后判断若上一个节点为空,则当前节点为空或当前节点的值比指定节点的值大,直接将当前节点设置为指定节点,插入到链首。若上一个节点不为空,直接将指定节点插入到二者之间(当前节点和上一个节点)。
def add(self, item):
current = self.head
previous = None
while current is not None:
if current.get_data() > item:
break
previous = current
current = current.get_next()
temp = Node(item)
if previous is None:
temp.set_next(self.head)
self.head = temp
else:
temp.set_next(current)
previous.set_next(temp)
其他方法也可以按照类似的方式实现,其中pop方法同无序链表。