目录
一、什么是有序表orderedlist ?
有序表是一种数据项依照某种可比性质(如整数大小、字母表先后)来决定在列表中的位置。
越小的数据项越靠近列表的头,越靠前。
二、orderedlist定义的操作
有序表数据定义的操作如下:
List(): 创建一个空的有序表
add(item): 添加一个数据项到列表中,并保持整体的顺序,假设item原先不存在与列表中
remove(item): 从列表中移除item,这时列表被修改,item原先应该存在于列表中
search(item): 在列表中查找item,返回的是bool类型值
isEmpty(): 返回列表是否为空
size(): 返回列表包含了多少数据项
index(item): 返回数据项在列表中的位置,此项应该存在
pop(): 从列表末尾移除数据项,假设原列表至少一个数据项
pop(pos): 移除位置pos的数据项
三、有序表OrderedList的实现
在实现有序表的时候需要记住的是,数据项的相对位置,取决于他们之间的大小比较。
以整数数据项为例,(17,26, 31, 54, 77, 93)的链表形式如图:
我们同样采用链表的形式实现,首先也是设置一个head来保存链表表头的引用。
class Orderedlist:
def __init__(self):
self.head = None
对于isEmpty/size/remove这些方法,与节点的次序无关,所以它们的实现跟underedlist是一样的。但是search和add方法需要修改。
1、search方法
在无序表的search中,如果要查找的数据项不存在,则需要遍历整个链表,直到表尾。
但是对于有序表来说,可以利用链表节点有序排列的特性,来为search节省不存在数据项的查找时间。当数据项不存在时,可以节省时间。
怎么做到的呢?就是一旦当前节点的数据项大于所要查找的数据项,则说明链表后面已经不可能再有要查找的数据项,可以直接返回False。
如下图中要查找数据项45:
代码实现:
def search(self, item):
current = self.head
found = False
stop = False
while current != None and not found and not stop:
print(current.getData())
if current.getData() == item:
found = True
else:
if current.getData() > item:
stop = True
else:
current = current.getNext()
return found
2、add方法
相对与无序表,add方法的变化比较大。因为add方法必须保证加入的数据项添加在合适的位置,以维护整个链表的有序性。
比如在有序表(17, 26, 54, 77, 93)中,加入数据项31,则需要沿着链表,找到第一个比31大的数54,将31插入到54的前面。
由于涉及到插入位置是当前的节点之前,而单链表无法得到前驱节点的引用,所以要跟remove方法类似,引入一个previous的引用,跟随当前节点current。一旦找到第一个比31大的数,previous就派上用场了。
代码实现:
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 is None: # 第一个节点就比要插入的数据大
temp.setNext(self.head)
self.head = temp
else:
temp.setNext(current) # 和下一行不能反了
previous.setNext(temp)
3、所有代码
class Node():
def __init__(self, initdata):
self.data = initdata
self.next = None
def getData(self):
return self.data # 返回的数据项
def getNext(self):
return self.next # 返回next
def setData(self, newdata):
self.data = newdata # 设置新的数据项
def setNext(self, newnext):
self.next = newnext
class Orderedlist:
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 is None: # 第一个节点就比要插入的数据大
temp.setNext(self.head)
self.head = temp
else:
temp.setNext(current) # 和下一行不能反了
previous.setNext(temp)
def size(self):
current = self.head
count = 0
while current != None:
count += 1
current = current.getNext()
return count
def search(self, item):
current = self.head
found = False
stop = False
while current != None and not found and not stop:
print(current.getData())
if current.getData() == item:
found = True
else:
if current.getData() > item:
stop = True
else:
current = current.getNext()
return found
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 previous == None: # current是首个节点的情况
self.head = current.getNext()
else:
previous.setNext(current.getNext())
四、链表实现的算法分析
对于链表算法复杂度的分析,主要看相应的方法是否涉及到链表的遍历。
当链表包含的节点数为n时:
- isEmpty是O(1),因为仅需要检查head是否为None
- size是O(n),因为必须遍历到表尾
- search/remove以及有序表的add方法,则是O(n),因为涉及到表的遍历,按照概率其平均操作的次数是n/2
- 无序表的add方法是O(1),因为仅需要插入到表头。
链表实现的List,跟python内置的列表数据类型,在有些方法的实现上时间复杂度不同,主要是因为python内置的列表数据类型是基于顺序存储来实现的,并进行了优化。