队列Queue
队列是一种有次序的数据集合,其特征是:
新数据项的添加总发生在一端(通常称为“尾端rear”)
现存数据项的移除总发生在另一端(通常称为“首端”front)
队列中入口和出口分别只有一个,不允许数据项直接插入队中,也不允许从队列中间移除数据项
数据项加入队列时首先出现在队尾,随着队首数据项的移除,它逐渐靠近队首。
这种次序安排的原则称为FIFO(first-in first-out)先进先出
用Python中的List实现:
class queue():
'''
ADT Queue
将第0位作为队首
'''
def __init__(self):
'使用list实现队列'
self.items = []
def enqueue(self, item):
'将数据项item添加到队尾'
self.items.append(item)
def dequeue(self):
'将数据项从队首移除'
return self.items.pop(0)
def isEmpty(self):
'判断队列是否为空'
return self.items == []
def size(self):
'返回队列长度'
return len(self.items)
def tolist(self):
'转化为列表'
return self.itemsclass queue():
- 注意:将第0位作为队首,那么添加数据的操作复杂度为 O ( 1 ) O(1) O(1),移除数据项的操作复杂度为 O ( n ) O(n) O(n)。将第0位作为队尾则反之。
双端队列Deque
双端队列是一种有次序的数据集,于队列类似,其两端可以成为首段和尾端。但deque中的双端都可以加入数据项,也可以移除。
从某种意义上来说,双端队列集成了栈和队列的能力。
双端队列并不具有内在的LIFO或FIFO的特性
用Python中的List实现:
class deque():
'''
ADT deque
第0位为队首
'''
def __init__(self):
'使用list实现双端队列'
self.items = []
def addFrout(self,item):
'将item加入队首'
self.items.insert(0,item)
def addRear(self,item):
'将item加入队尾'
self.items.append(item)
def removeFront(self):
'移除队首数据项,并返回'
return self.items.pop(0)
def removeRear(self):
'移除队尾数据项,并返回'
return self.items.pop(-1)
def isEmpty(self):
return self.items == []
def size(self):
return len(self.items)
def tolist(self):
return self.items
- 注意:第0位为队首,则队首添加或移除数据的操作复杂度为 O ( n ) O(n) O(n),队尾添加或删除数据的操作复杂度为 O ( 1 ) O(1) O(1)。如果第0位为队尾则反之。
双端队列的简单应用:回文词
回文词是正读反读都一样的词。比如12321,radar,madam,上海自来水来自海上,山东落花生花落东山……
利用双端队列很容易解决回文词问题。首先将回文词添加到双端队列,再从两端同时移除字符并判定是否相同,如不同则返回否,如果相同就继续移除并判定,直到deque中剩下0个或1个字符,返回是。
from custom_data_type import deque
def palchecker(string):
chardeque = deque()
for token in string:
chardeque.addRear(token)
stillEqual = True
while stillEqual and chardeque.size() > 1:
first = chardeque.removeFront()
rear = chardeque.removeRear()
if first != rear:
stillEqual = False
return stillEqual
链表
无序表UnorderdList
链表是一种数据项按照相对位置存放的数据集
Python中的列表在移除中间位置的一个数据项时,后面的数据要依次向前移动。因此这样的操作复杂度为 O ( n ) O(n) O(n)。这样的设计有Python自己的考虑
但是我们为了使移除任意数据项的操作复杂度为 O ( 1 ) O(1) O(1),可以使用链接表的方案实现List。
**虽然无序表要求保持数据项前后的相对位置,但不要求数据项必须存放在连续的存储空间。**我们可以使数据项之间建立链接指向,这样即使数据项不在连续的存储空间依然可以保持其前后的相对位置。
链表实现的最基本元素是节点Node。每个节点要包含两个信息:数据项和下一个节点的引用信息。
引用信息如果为None则没有下一个节点。
class Node:
'''
定义节点
'''
def __init__(self, initdata) -> None:
self.data = initdata
self.next = None
def getData(self):
return self.data
def getNext(self):
return self.next
def setData(self, newdata):
self.data = newdata
def setNext(self, newnext):
self.next = newnext
class UnorderdList:
'''
无序链表
'''
def __init__(self) -> None:
self.head = None
def add (self, item):
temp = Node(item)
temp.setNext(self.head)
self.head = 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
while current != None and not found:
if current.getData() == item:
found = 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:
self.head = current.getNext()
else:
previous.setNext(current.getNext())
有序表OrderdList
有序表与无序表类似,但是依据某种数据项的可比性质(比如数字的大小)来决定在列表中的位置。
由于的Python的可拓展性,对数据项的讨论不限于数字,可适用于所有定义了__gt__
(富比较)方法的数据类型
有序表依然使用链表的实现方法,Node定义相同
class orderedList:
'''
有序表
'''
def __init__(self) -> None:
self.head = Node
def isEmpty(self):
return self.head == None
def size(self):
current = self.head
count = 0
while current != None:
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 previous == None:
self.head = current.getNext()
else:
previous.setNext(current.getNext())
def search(self, item):
current = self.head
found = False
stop = False
while current != None and not found and not stop:
if current.getData() == item:
found = True
else:
if current.getData() > item:
stop = True
else:
current = current.getNext()
return found
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)