- 双向队列:
双端队列是一种有次序的数据集,数据项既可以从队首加入,也可以从队尾加入,数据项也可以从两端删除;某种意义上说,双端队列集成了栈和队列的能力。
但双端队列并不具有内在的LIFO和FIFO特性,如果用双端队列来模拟栈和队列,需要由使用者自行维护操作的一致性。- 双向队列的操作:
deque() 创建空双端队列
addfront(item) 将item加入队首
addrear(item) 将item加入队尾
removefront() 从队首移除数据项,返回值为移除的数据项
removerear() 从队尾移除数据项,返回值为移除的数据项
isempty() 返回deque是否为空
size() 返回deque中包含数据项的个数**
举例如:
用代码实现为:
- 双向队列的操作:
class Deque(object):
def __init__(self):
self.items = []
def is_empty(self):
return self.items == []
def add_front(self, item):
self.items.append(item)
def add_rear(self, item):
self.items.insert(0, item)
def remove_front(self):
return self.items.pop()
def remove_rear(self):
return self.items.pop(0)
def size(self):
return len(self.items)
- 双向队列的应用–回文检测
“回文”即为正读和反读相同的一个字符串(中文或英文皆可)。
算法思想:
用双端队列很容易解决回文词问题,先将需要判定的词从队尾加入deque,再从两端同时移除字符判定是否相同,直到deque中剩下0个或1个字符。
(考虑回文的字数为奇数偶数不同的情况)
自写为:
def palchecker(astring):
deque = Deque()
wordchecker = True
for i in astring:
deque.addrear(i)
while deque.size() > 1 and wordchecker :
temp1 = deque.removerear()
temp2 = deque.removefront()
if temp1 != temp2:
wordchecker = False
return wordchecker
print(palchecker('aialblaia'))
print(palchecker('word'))
缺点为所用变量名不够准确,代码自解释性笔记差。
标准代码为
def palchecker(aString):
chardeque = Deque()
for ch in aString:
chardeque.addrear(ch)
stillEqual = True
while chardeque.size() > 1 and stillEqual:
first = chardeque.removefront()
last = chardeque.removerear()
if first != last:
stillEqual = False
return stillEqual
print(palchecker("lsdkjfskf"))
print(palchecker("radar"))
-
链表实现的无序表UnorderedList -
- 什么是无序表?
虽然列表数据结构要求保持数据项的前后相对位置,但这种前后位置的保持,并不要求数据项依次存放在连续的存储空间。
如下图,数据项存放位置并没有规则,但如果在数据项之间建立链接指向,就可以保持其前后相对位置。第一个和最后一个数据项需要显示标记出来,一个是队首,一个是队尾,后面再无数据了。即为无序表。
- 什么是无序表?
- 链表实现结点Node:
链表实现的最基本元素是节点Node,每个节点至少要包含两个信息:数据项本身、以及指向下一个节点的引用信息。注意next为None的意义是没有下一个节点了。
链表实现无序表UnorderedList
可以采用链接节点的方式构建数据集来实现无序表。
- 链表实现无序表UnorderedList
链表的第一个和最后一个节点最重要。如果想访问到链表中的所有节点,就必须从一个节点开始沿着链接遍历下去。
所以无序表必须要有对第一个节点的引用信息,设立一个属性head,保存对第一个节点的引用,空表的head为None。
随着数据项的加入,无序表的head始终指向链条的第一个节点,无序表mylist对象本身并不包含数据项(数据项在节点中)。其中包含的head只是对首个节点Node的引用,判断空表的isEmpty()很容易实现。
无序表实现add方法,按照实现的性能考虑,应该添加到最容易加入的位置上,也就是表头,整个链表的首位置。
如下图:
- 链表实现 size
从链表头head开始遍历到表尾同时用变量累加经过的节点个数。
- 链表实现 search
从链表头head开始遍历到表尾,同时判断当前节点的数据项是否为目标。
关键点:链表实现:remove(item)方法
首先找到item,这个过程和search一样,但删除节点时,需要特别的技巧。
current指向的是当前匹配数据项的节点,而删除需要把前一个节点的next指向current的下一个节点,所以我们在查找current的同时,还要维护前一个(previous)节点的引用。
找到item后,current指向item节点,previous指向前一个节点,开始执行删除,需要区分两种情况:current是首个节点;或者是位于链条中间的节点。
无整体标准代码,按局部修改为
class Node:
def __init__(self,initdata):
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 UnorderedList:
def __init__(self):
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 = 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())
- 采用链表实现有序表OrderedList
在实现有序表时,需要记住数据项的相对位置,取决于他们之间的“大小”比较,Node定义相同,OrderedList也设置一个head来保存链表表头的引用。
对于isEmpty(),size(),remove()方法与节点次序无关,其实现与UnorderedList相同。
search和add方法需要修改。- 有序表实现:search方法:
在无序表的search中,如果需要查找的数据项不存在,则会搜遍整个链表,直到表尾。
对于有序表来说,可以利用链表节点有序排列的特性,来为search节省不存在数据项的查找时间。一旦当前节点的数据项大于所要查找的数据项,则说明链表后面已经不可能再有要查找的数据项,可以直接返回False。 - 有序表实现:add方法
add方法必须保证加入的数据项添加在合适的位置,以维护整个链表的有序性。
从头找到第一个比添加项大的数据项,将添加项插到该数据项前面。
跟remove方法类似,引入一个previous,跟随当前节点current。
- 有序表实现:search方法:
同上代码为:
class Node:
def __init__(self,initdata):
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 OrderedList:
def __init__(self):
self.head = None
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)