实现基于array和linked的stack

除了栈中__iter__方法外,其余复杂度都小于O(1)。数组容量翻倍的时候,数组push方法复杂度变为O(n) ,其他时候是O(1)。

数组、链表实现pop方法复杂度都是O(1)。

两种实现中__iter__方法都是线性时间运行的,但是在链表实现中使用递归函数,导致内存线性增长,可以使用双链表来避免这个问题。

n个对象,栈需要的总空间是2n+2,数组需要的总空间是数组容量+2

当数组的装载因子大于1/2,数组实现比链表实现具有更高的效率。

#! /usr/bin/env python
# -*- coding: utf-8 -*-

'''
@author: liudaoqiang
@file: studycase
@time: 2018/9/3 6:28
file: arraystack.py
'''

class Node(object):

	def __init__(self, data, next):
		self.data = data
		self.next = next

	def __iter__(self):
		cursor = self
		while cursor != None:
			yield cursor.data
			cursor = cursor.next

class Array(object):

	def __init__(self, capacity, fillValue = None):
		self._items = list()
		for item in range(capacity):
			self._items.append(fillValue)

	def __iter__(self):
		return iter(self._items)

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

	def __str__(self):
		return str(self._items)

	def __getitem__(self, index):
		return self._items[index]

	def __setitem__(self, index, newItem):
		self._items[index] = newItem


class AbstractCollection(object):

	def __init__(self, sourceCollection):
		self._size = 0
		if sourceCollection:
			for item in sourceCollection:
				self.add(item)

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

	def __add__(self, other):
		result = type(self)(self)
		for item in other:
			result.add(item) # add方法在type(self)中一定要实现
		return result
	def __len__(self):
		return self._size

	def __str__(self):
		return str(self)

	def __eq__(self, other):
		if self is other: return True
		if type(self) != type(other) or\
			len(self) != len(other):
			return False
		otherItem = iter(other) # iter为内置函数
		for item in self:
			if item != next(otherItem):
				return False
		return True


class AbstractStack(AbstractCollection):
	"""AbstractStack of ArrayStack and LinkedStack"""
	def __init__(self, sourceCollection=None):
		AbstractCollection.__init__(self, sourceCollection)
		# if sourceCollection:
		# 	for item in sourceCollection:
		# 		self.add(item)
	def add(self, item):
		self.push(item) # 在ArrayStack和LinkedStack实现push方法


class LinkedStack(AbstractStack):

	def __init__(self, sourceCollection=None):
		self._items = None
		AbstractStack.__init__(self, sourceCollection)

	# Accessors
	def __iter__(self):
		def visitNode(node):
			if not node is None:
				visitNode(node.next)
				tempList.append(node.data)
		tempList = list()
		visitNode(self._items)
		return iter(tempList)

	def peek(self):
		if self.isEmpty():
			raise KeyError("The Stack is empty")
		return self._items.data

	def __str__(self):
		return "{" + " ,".join(map(str, iter(self))) + "}"

	# Mutator
	def add(self, item):
		self.push(item)

	def clear(self):
		self._size = 0
		self._items = None

	def push(self, item):
		self._items = Node(item, self._items)
		self._size += 1

	def pop(self):
		if self.isEmpty():
			raise KeyError("The stack is empty")
		oldItem = self._items.data
		self._items = self._items.next
		self._size -= 1
		return oldItem

class ArrayStack(AbstractStack):
	"""An array-based stack implementation"""
	DEFAULT_CAPACITY = 10 # for all array stacks

	def __init__(self, sourceCollection=None):
		"""Sets the initial state of self, which includes the
		contents of sourceCollection, if it's present"""
		self._items = Array(ArrayStack.DEFAULT_CAPACITY)
		AbstractStack.__init__(self, sourceCollection)

	# Accessors 访问器
	def __iter__(self):
		"""Supports iteration over a view of self.
		Visits items from bottom to top of stack"""
		cursor = 0
		while cursor < len(self):
			yield self._items[cursor]
			cursor += 1

	def peek(self):
		"""Returns the item ad top of the stack.
		Precondition: the stack is not empty.
		Raises KeyError if the stack is empty."""
		if len(self) == 0:
			raise KeyError("stack is empty.")
		return self._items[len(self) - 1]

	# Mutator 改变器,改变实例对象
	def add(self, item):
		self.push(item)

	def clear(self):
		"""Makes self become empty"""
		self._size = 0

	def __str__(self):
		return "{" + ", ".join(map(str, self._items)) + "}"

	def push(self, item):
		"""Inserts item at top of the stack"""
		# Resize array here if necessary
		# print(type(self))
		self._items[len(self)] = item
		self._size += 1
		if len(self) >= ArrayStack.DEFAULT_CAPACITY:
			temp = Array(len(self) + 1)
			# print(len(self))
			for i in range(len(self)):
				temp._items[i] = self._items[i]
				# print(self._items[i])
			self._items = temp

	def pop(self):
		"""Removes and returns the item at top of the stack
		Precondition: the stack is not empty.
		Raises KeyError if the stack is empty.
		Postcondition: the top item is removed from the stack."""
		if len(self._items) == 0:
			raise KeyError("stack is empty.")
		oldItem = self._items[len(self) - 1]
		self._size -= 1
		temp = ArrayStack()
		if self._size <= ArrayStack.DEFAULT_CAPACITY // 4:
			temp._items = Array(ArrayStack.DEFAULT_CAPACITY // 2)
			for i in range(len(self)):
				temp._items[i] = self._items[i]
			self._items = temp._items
		# Resize the array here if necessary
		return oldItem


"""
Length: 0
Empty: True
Push 1-10
Peeking: 10
Items (bottom to top): {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, None}
Length: 10
Empty: False
<class '__main__.ArrayStack'>
True
True
{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, None}
Length of clone after clear: 0
Push 11
Popping items (top to bottom):11 10 9 8 7 6 5 4 3 2 1 
Length: 0
Empty: True
=======================
Length: 0
Empty: True
Push 1-10
Peeking: 10
Items (bottom to top): {1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,9 ,10}
Length: 10
Empty: False
<class '__main__.LinkedStack'>
True
True
{1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,9 ,10 ,1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,9 ,10}
Length of clone after clear: 0
Push 11
Popping items (top to bottom):11 10 9 8 7 6 5 4 3 2 1 
Length: 0
Empty: True
"""
def test(stackType):
	s = stackType()
	print("Length:", len(s))
	print("Empty:", s.isEmpty())
	print("Push 1-10")
	for i in range(10):
		s.push(i + 1)
	print("Peeking:",s.peek())
	print("Items (bottom to top):", s)
	print("Length:", len(s))
	print("Empty:", s.isEmpty())
	print(type(s))
	theClone = stackType(s)
	print(s == theClone)
	# theClone._items[9] = 0
	print(s == theClone)
	print(s + theClone)
	theClone.clear()
	print("Length of clone after clear:", len(theClone))
	print("Push 11")
	s.push(11)
	print("Popping items (top to bottom):", end="")
	while not s.isEmpty(): print(s.pop(), end=" ")
	print("\nLength:", len(s))
	print("Empty:",s.isEmpty())

if __name__ == "__main__":
	test(ArrayStack)
	print("=======================")
	test(LinkedStack)

猜你喜欢

转载自blog.csdn.net/liudaoqiang_tj/article/details/82343444