赞
踩
接下来我们研究有序链表。
如果给定一个链表,他的节点数据元素都是的整数,如77, 26, 31, 93, 17, 54。如果这些链表里的节点是以升序排列的有序链表,那么它会被写作17, 26, 31, 54, 77, 93。由于 17 是最小的元素,因此它就成了链表的第一个元素(视为节点)。同理,由于 93 是最大的元素,因此它就会在链表的最后一个位置。
在有序链表中,元素的相对位置取决于它们的基本特征。它们通常以升序或者降序排列,并且我们假设元素之间能进行有意义的比较。有序链表的众多操作与无序链表的相同。
我们来思考一下有序链表的基本方法:
在实现有序链表时必须记住,元素的相对位置取决于它们的基本特征。整数有序链表 17, 26, 31, 54, 77, 93 可以用如下图所示的链式结构来表示。
相比于无序链表,有序链表节点的构造方法并不发生变化,如下:
# 构造节点 class Node: def __init__(self, initdata): self.data = initdata # 数据元素 self.next = None # 指向下一节点的引用(python变量赋值的本质是引用) def getData(self): # 获取节点的数据元素值 return self.data def getNext(self): # 获取下一节点的引用 若有节点则直接视作为下一节点 return self.next def setData(self, newdata): # 给节点的数据元素设置值 self.data = newdata def setNext(self, newnext): # 给节点设置对下一节点的引用
有序链表与无序链表的构造方法是相同的,都是 head 引用指向 None,代表是一个空链表。如下所示:
class OrderedLinkList:
def __init__(self):
self.head = None
因为 isEmpty 和 length 仅与链表中的节点数目有关,而与实际的元素值无关,所以这两个方法在有序链表中的实现与在无序链表中一样。同理,由于仍然需要找到目标元素并且通过更改链接来移除节点,因此 remove 方法的实现也一样。
isEmpty、length、remove 方法实现如下:
class OrderedLinkList: def __init__(self): self.head = None def isEmpty(self): return self.head == None def length(self): current = self.head count = 0 while current != None: count = count + 1 current = current.getNext() return count def remove(self, item): current = self.head previous = None found = False while not found: if current.getData() == item: found = True else: previous = current current = current.getNext() if current == None: return False if previous == None: self.head = current.getNext() else: previous.setNext(current.getNext())
剩下的两个方法,search 和 add ,都需要做一些修改。
在无序链表中搜索时,需要逐个遍历节点,直到找到目标节点或者没有节点可以访问。这个方法同样适用于有序链表,但前提是链表必须包含目标元素。如果目标元素不在链表中,可以利用元素有序排列这一特性尽早终止搜索(代码第12~13行)。
search 方法实现如下:
class OrderedLinkList: def __init__(self): self.head = None def search(self, item): current = self.head found = False while current != None and not found: if current.getData() == item: found = True else: if current.getData() > item: return False else: current = current.getNext() return found
需要修改最多的是 add 方法。对于无序链表,add 方法可以简单地将一个节点放在链表的头部,这是最简便的访问点。不巧,这种做法不适合有序链表。我们需要在已有链表中为新节点找到正确的插入位置。
假设要向有序链表 17, 26, 54, 77, 93 中添加 31。add 方法必须确定新元素的位置在 26 和 54 之间。下图展示了我们期望的结果。像之前解释的一样,需要遍历链表来查找新元素的插入位置。当访问完所有节点(current指向None )或者当前值大于要添加的元素时,就找到了插入位置。在本例中,遇到 54 使得遍历过程终止。
add 方法实现代码如下:
class OrderedLinkList: def __init__(self): self.head = None def add(self, item): current = self.head previous = None stop = False while current != None and not stop: if current.getData() > item: stop = True else: previous = current current = current.getNext() temp = Node(item) if previous == None: temp.setNext(self.head) self.head = temp else: temp.setNext(current) previous.setNext(temp)
和无序链表一样,由于 current 无法提供对将要修改节点的访问,因此使用额外的引用 previous 是十分必要的。上述代码中第 7~8 行初始化两个外部引用,第 13~14 行保证 previous 一直跟在current 后面。只要还有节点可以访问,并且当前节点的值小于或等于要插入的元素,判断条件就会允许循环继续执行。在循环停止时,就找到了新节点的插入位置。
一旦创建了新节点,唯一的问题就是它会被添加到链表的开头还是中间某个位置。previous == None (第17行)提供了解决方法。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。