python数据结构与算法——(二)队列和栈

上节内容回顾:python数据结构与算法——(一)数组列表和链表

本节中介绍队列(queue)和栈(stack)。队列和栈很类似,不同的是,队列是先进先出结构(FIFO, first in first out),如日常生活中的排队;而栈是后进先出结构(LIFO, last in first out),如在桌子上放一沓书,先放的一本在最下面,最后放的一本在最上面,而拿的时候是先拿最上面的一本。

1. 队列

队列需要从头删除元素,从尾部增加元素。下面有几种方式实现队列。

1.1 用list实现

class ListQueue(object):
	def __init__(self):
		self.items = []

	def isEmpty(self):
		return self.items == []

	def push(self,item):
		self.items.append(item)

	def pop(self):
		return self.items.pop(0)

	def size(self):
		return len(self.items)

详细代码见github:list_queue.py

用list,直接调用list的方法可以很容易实现队列,但list.pop(0)会导致所有list元素前移,时间复杂度为O(n)。append的时间复杂度为O(1),但如果内存不够还需要重新分配内存。所以用这个方式的效率是非常低的。

1.2 用链表实现

在上一节中,我们实现了单链表LinkedList。LinkedList有popleft和append这两个方法,且都是O(1)。因此可以高效实现队列。

class FullError(object):
	pass
class EmptyError(object):
	pass

class Queue(object):
	def __init__(self, maxsize=None):
		self.maxsize = maxsize 
		self._item_link_list = LinkedList(self.maxsize)

	def __len__(self):
		return len(self._item_link_list)

	def push(self,value):
		"""队尾添加元素"""
		if self.maxsize is not None and len(self) >= self.maxsize:
			raise FullError('queue full')
		return self._item_link_list.append(value)

	def pop(self):
		""" 队列头部删除元素"""
		if len(self) <= 0:
			raise EmptyError('empty queue')
		return self._item_link_list.popleft()

详细代码见github:queue.py

1.3 用数组实现

因为数组是预先分配固定内存,如果知道队列的最大长度,也可用数组实现。
用两个指针head和tail,当我们向数组中增加元素push时,head指针前移;当我们删除元素pop时,tail指针前移。队列的长度是head-tail,且此长度不能超过初始化长度。如果head指针已经到数组未尾后,则又回到头部重新开始,如0,1,2,3,4,0,1,2,3,4,…,如此循环下去。
下面我们用上一节的Array ADT实现。

class FullError(object):
	pass

class ArrayQueue(object):
	def __init__(self, maxsize):
	    self.maxsize = maxsize 
		self.array = Array(self.maxsize)
		self.head = 0 
		self.tail = 0 
	
	def __len__(self):
		return self.head - self.tail

	def push(self,value):
		if len(self) >= self.maxsize:
			raise FullError('queue full')
		self.array[self.head % self.maxsize] = value
		self.head += 1

	def pop(self):
		value = self.array[self.tail % self.maxsize]
		self.tail += 1
		return value

详细代码见github:array_queue.py

2. 双端队列

双端队列,在队头和队尾都能进出,即拥有append、appendleft、pop、popleft这几个方法。在python内置中也有双端队列,collection.deque模块。

2.1 双链表实现双端队列

在上一节中,我们实现了双链表CircularDoubleLinkedList ADT,下面用它实现双端队列。

class Deque(CircularDoubleLinkedList):
	def pop(self):
		"""删除尾部节点"""
		if len(self) == 0:
			raise Exception('empty')
		tailnode = self.tailnode()
		value = tailnode.value 
		self.remove(tailnode)
		return value

	def popleft(self):
		"""删除头部节点"""
		if len(self) == 0:
			raise Exception('empty')
		headnode = self.headnode()
		value = headnode.value
		self.remove(headnode)
		return value 

详细代码见github:deque.py

2.2 python内置deque实现队列

from collections import deque
class PythonDequeQueue(object):
	def __init__(self, maxsize=None):
		self.maxsize = maxsize
		self._item_python_deque = deque(maxlen=self.maxsize)

	def __len__(self):
		return len(self._item_python_deque)

	def push(self):
		"""队尾添加元素"""
		if self.maxsize is not None and len(self) >= self.maxsize:
			raise FullError('queue full')
		return self._item_python_deque.append(value)

	def pop(self):
		"""队列头部删除元素"""
		if len(self) <= 0:
			raise EmptyError('empty queue')
		return self._item_python_deque.popleft()

详细代码见github:python_deque_queue.py

3. 栈

栈(stack),先进后出结构,即在尾部增删元素,下面有几种方式实现。

3.1 deque实现栈

用刚刚实现的双端队列实现栈。

class Stack(object):
	def __init__(self):
		self.deque = Deque()
	
	def push(self,value):
		return self.deque.append(value)

	def pop(self):
		return self.deque.pop()

	def __len__(self):
		return len(self.deque)

	def is_empty(self):
		return len(self) == 0 

也可用python内置的deque实现,将stack的__init__方法中,deque替换为python的deque模块。

from collections import deque
self.deque = deque()

详细代码见github:stack.py

3.2 数组实现栈

因为stack是先进后出结构,只用一个指针即可实现。

class ArrayStack(object):
    def __init__(self,maxsize):
        self.maxsize = maxsize
        self.array = Array(self.maxsize)
        self.tail = 0

    def __len__(self):
        return self.tail

    def push(self,value):
        if len(self) >= self.maxsize:
            raise FullError('stack full')
        self.array[self.tail] = value
        self.tail += 1

    def pop(self):
        if len(self) == 0:
            raise Exception('stack empty')
        value = self.array[self.tail - 1]
        self.tail -= 1
        return value

    def is_empty(self):
        return len(self) == 0

详细代码见github:array_stack.py

4. reference

本文同步发布在我的github.io

猜你喜欢

转载自blog.csdn.net/weixin_43004311/article/details/82695570