除了栈中__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)