栈和队列都是一种动态集合。栈实现后进先出(last-in, first-out, LIFO)的策略:最后进入的元素被最先删除。队列实现先进先出(first-in, first-out, FIFO)的策略:最先进入的元素被最先删除。
下面实现了书中的栈,包括:
class MyStack:
def __init__(self, maxsize):
self.__maxsize = maxsize
self.__top = -1
self.__S = [0]*maxsize # 当作普通数组
def stack_empty(self):
return self.__top == -1
def stack_full(self):
return self.__top + 1 == self.__maxsize
def push(self, x):
if self.stack_full():
print("Stack is full!")
return
else:
self.__top += 1
self.__S[self.__top] = x
def pop(self):
if self.stack_empty():
print("Stack is empty!")
return
else:
self.__top -= 1
return self.S[self.__top+1]
def stack_print(self):
for i in range(self.__top+1):
print(self.__S[i], end=' ')
def test():
s = MyStack(8)
s.pop() # Stack is empty!
for i in range(8):
s.push(i)
s.push(8) # Stack is full!
s.stack_print()
if __name__ == '__main__':
test()
下面实现了书中的队列,包括:
class MyQueue:
def __init__(self, maxsize):
self.__maxsize = maxsize
self.__head = 0
self.__tail = 0 # 该位置不存放元素
self.__S = [0]*maxsize # 当作普通数组
def queue_empty(self):
return self.__head == self.__tail
def queue_full(self):
return self.__head == (self.__tail+1) % self.__maxsize
def enqueue(self, x):
if self.queue_full():
print("Queue is full!")
return
self.__S[self.__tail] = x
self.__tail = (self.__tail + 1) % self.__maxsize
def dequeue(self):
if self.queue_empty():
print("Queue is empty!")
return
x = self.__S[self.__head]
self.__head = (self.__head + 1) % self.__maxsize
return x
def queue_print(self):
begin = self.__head
end = self.__tail
if self.__tail < self.__head:
end = self.__tail + self.__maxsize
for i in range(begin, end):
print(self.__S[i % self.__maxsize], end=' ')
def queue_print_all(self):
print(self.__S)
def test():
q = MyQueue(6)
q.dequeue() # Queue is empty!
for i in range(1,6):
q.enqueue(i)
q.enqueue(6) # Queue is full!
q.queue_print()
print()
q.dequeue()
q.enqueue(6)
q.queue_print_all()
q.queue_print()
print()
q.dequeue()
q.enqueue(7)
q.queue_print_all()
q.queue_print()
if __name__ == '__main__':
test()
链表是一种链式结构,其中的对象按线性排列。与数组不同,链表的顺序由各个对象里的指针的决定,为动态集合提供了一种简单而领过的表示方法。双向链表(doubly linked list)中的每一个对象包含一个数据和两个指针(next和prev),头指针指向链表第一个结点,即头结点,尾指针指向最后一个结点,即尾结点。其中头指针必须存在,尾指针可有可无。
书中P131中简单的双向链表L包含一个指向链表头结点的指针L.head。如果L.head为空,则链表为空。
下面实现了该链表,包括:
class DLListNode:
'''Double linked list node'''
def __init__(self, val=None, prev=None, nex=None):
self.val = val
self.prev = prev
self.next = nex
class DLList:
'''Double linked list with a head pointer and without sentinel'''
def __init__(self):
self.__head = None
def empty(self):
return not self.__head
def insertTail(self, val):
'''Insert a node with val in tail'''
if self.empty():
self.insertHead(val)
else:
new_node = DLListNode(val, None, None)
cur = self.__head
while cur and cur.next:
cur = cur.next
new_node.prev = cur
cur.next = new_node
def insertHead(self, val):
'''Insert a node with val in head'''
new_node = DLListNode(val, None, self.__head)
if self.empty():
self.__head = new_node
else:
self.__head.prev = new_node
self.__head = new_node
def search(self, val):
'''Return the first node with val. If not, return None'''
cur = self.__head
while cur and cur.val != val:
cur = cur.next
return cur
def delete(self, val):
'''Delete the first node whose val is val'''
node_deleted = self.search(val)
if self.__head == node_deleted:
node_deleted.next.prev = None
self.__head = node_deleted.next
else:
node_deleted.prev.next = node_deleted.next
node_deleted.next.prev = node_deleted.prev
del node_deleted
def print(self):
if self.empty():
print('Linked list is empty!')
return
cur = self.__head
while cur:
print(cur.val, end=' ')
cur = cur.next
def test():
dll = DLList()
dll.print() # Linked list is empty!
for i in range(5):
dll.insertHead(i)
dll.print() # 4 3 2 1 0
print()
for i in range(5):
dll.insertTail(i)
dll.print() # 4 3 2 1 0 0 1 2 3 4
print()
for i in range(5):
if dll.search(i):
print("Find node", i)
for i in range(5):
print("Delete node %d:" % i, end=' ')
dll.delete(i)
dll.print()
print()
if __name__ == '__main__':
test()
书中P133中带哨兵结点的双向循环链表L(circular, doubly linked list with a sentinel)稍微复杂一些,增加了一个哨兵L.nil。该链表包含几个性质:
下面实现了该链表,包括:
class DLListNode:
'''Double linked list node'''
def __init__(self, val=None, prev=None, nex=None):
self.val = val
self.prev = prev
self.next = nex
class CDDList:
'''Circular double linked list with a sentinel'''
def __init__(self):
self.__nil = DLListNode() # __nil points to a sentinel
self.__nil.prev = self.__nil
self.__nil.next = self.__nil
def empty(self):
return self.__nil.next == self.__nil and self.__nil.prev == self.__nil
def insertTail(self, val):
'''Insert a node with val in tail'''
tail = self.__nil.prev
new_node = DLListNode(val, tail, self.__nil)
tail.next = new_node
self.__nil.prev = new_node
def insertHead(self, val):
'''Insert a node with val in head'''
new_node = DLListNode(val, self.__nil, self.__nil.next)
self.__nil.next.prev = new_node
self.__nil.next = new_node
def search(self, val):
'''Return the first node with val. If not, return None'''
cur = self.__nil.next
while cur and cur.val != val:
cur = cur.next
return cur
def delete(self, val):
'''Delete the first node whose val is val'''
node_deleted = self.search(val)
node_deleted.prev.next = node_deleted.next
node_deleted.next.prev = node_deleted.prev
del node_deleted
def print(self):
if self.empty():
print('Linked list is empty!')
return
cur = self.__nil.next
while cur is not self.__nil:
print(cur.val, end=' ')
cur = cur.next
def test():
dll = CDDList()
dll.print() # Linked list is empty!
for i in range(5):
dll.insertHead(i)
dll.print() # 4 3 2 1 0
print()
for i in range(5):
dll.insertTail(i)
dll.print() # 4 3 2 1 0 0 1 2 3 4
print()
for i in range(5):
if dll.search(i):
print("Find node", i)
for i in range(5):
print("Delete node %d:" % i, end=' ')
dll.delete(i)
dll.print()
print()
if __name__ == '__main__':
test()