接口、实现、多态、继承与抽象
Somehow the silence seemed to connect us in a way that words never could.
有时候,沉默胜过千言万语。
基本描述:
接口:用户可用的一组操作;(BagInterface)
实现:符合接口的函数、方法或类;(ArrayBag)
多态:在两个或多个实现种使用相同的运算符符号、函数名或方法。(多态函数str和len)
继承:复用已有模型构建新模型;(ArraySortedBag)
抽象:类的通用特征和行为;(AbstractBag)
关系图:
代码实现
1. 接口(BagInterface)
提供 for / in / >= / <= 等操作符接口
class BagInterface(object):
"""interface for all bag types"""
# constructor
def __init__(self, sourceCollection=None):
"""initial"""
pass
# accessor methods
def isEmpty(self):
"""return True if len(self) == 0, or False otherwise"""
return True
def __len__(self):
return 0
def __str__(self):
return ""
def __iter__(self):
return None
def __add__(self, other):
"""return a new bag containing the contents of self and other"""
return None
def __eq__(self, other):
return False
def __get__(self, index):
return None
# Mutator methods(add/delete/remove/clear)
def clear(self):
pass
def add(self, item):
pass
def remove(self, item):
pass
2. 基于数组实现(ArrayBag)与 基于链表实现(LinkedBag)
性能对比:
i. 数组增删O(n),查询O(1);连续内存地址,不能动态拓展。
ii. 链表增删O(1),查询O(n),非连续内存地址,可动态扩展。
2.1 ArrayBag
# 自定义数组
from arrays import Array
class ArrayBag (object):
DEFAULT_CAPACITY = 10
def __init__(self, sourceCollect=None):
self._items = Array(ArrayBag.DEFAULT_CAPACITY)
self._size = 0
if sourceCollect:
for item in sourceCollect:
self.add(item)
def isEmpty(self):
return len(self) == 0
def __len__(self):
return self._size
def __iter__(self):
cursor = 0
while cursor < len(self):
yield self._items[cursor]
cursor += 1
def __str__(self):
return "{"+", ".join(map(str, self)) + "}"
def __add__(self, other):
result = ArrayBag(self)
for item in other:
result.add(item)
return result
def __eq__(self, other):
if self is other:
return True
if type(self) != type(other) or len(self) != len(other):
return False
for item in self:
if not item in other:
return False
return True
def clear(self):
self._size = 0
self._items = Array(ArrayBag.DEFAULT_CAPACITY)
def add(self, item):
self._items[len(self)] = item
self._size += 1
# check array memory here and increase it if necessary
def remove(self, item):
if not item in self:
raise KeyError(str(item) + "not in bag")
targetIndex = 0
for targetItem in self:
if targetItem == item:
break
targetIndex += 1
for i in range(targetIndex, len(self)-1):
self._items[i] = self._items[i+1]
self._size -= 1
# check array memory here and decrease it if necessary
注意:Array 为基于list的自定义数组,可自动扩展数组大小
class Array(object): # 用list创建一位数组类;并定义数组的操作方法
def __init__(self, capacity, fillValue=None, logicalSize=0):
# 创建数组时就要定义数组大小
self.items = []
self.capacity = capacity
for count in range(capacity):
self.items.append(fillValue)
self.logicalSize = logicalSize
self.fillValue = fillValue
def __len__(self): # 物理大小
return len(self.items)
def size(self): # 逻辑大小
self.logicalSize = 0 # 每次调用都要初始化为0
for i in self.items:
if i != None:
self.logicalSize += 1
return self.logicalSize
def __str__(self):
# 字符串输入
return str(self.items)
def __iter__(self):
# 迭代器
return iter(self.items)
def __getitem__(self, index):
# 获取元素
if index >= 0 and index < Array.size(self):
return self.items[index]
else:
return 'IndexError'
def __setitem__(self, index, newItem):
# 给数组赋值
self.items[index] = newItem
logicalSize = Array.size(self)
def grow(self):
# 增加数组大小
logicalSize = Array.size(self)
if logicalSize >= (self.capacity//2) and logicalSize <= self.capacity:
self.capacity = self.capacity * 2
temp = Array(self.capacity)
for i in range(logicalSize):
temp[i] = self.items[i]
self.items = temp
return self.items
def shrink(self):
# 减小数组大小
logicalSize = Array.size(self)
if logicalSize <= (self.capacity//4) and 4 <= self.capacity:
self.capacity = self.capacity // 2
temp = Array(self.capacity)
for i in range(logicalSize):
temp[i] = self.items[i]
self.items = temp
return self.items
def insert(self, index, newItem):
# 指定位置插入
logicalSize = Array.size(self)
if logicalSize == self.capacity:
Array.grow()
if index < logicalSize and index >= 0:
for i in range(logicalSize, index, -1):
self.items[i] = self.items[i-1]
self.items[index] = newItem
elif index >= logicalSize:
self.items[logicalSize] = newItem
else:
print('error')
def pop(self, index):
# 指定位置删除
logicalSize = Array.size(self)
if index < logicalSize and index >= 0:
popValue = self.items[index]
for i in range(index, logicalSize):
self.items[i] = self.items[i+1]
self.items[logicalSize-1] = self.fillValue
else:
print('error')
return popValue
def __eq__(self, other):
flag = False
a = Array.size(self)
if isinstance(other, Array) and a == other.size():
while not flag and a > 0:
if self.items[a-1] != other[a-1]:
flag = False
return flag
a -= 1
flag = True
return flag
2. 2 基于链表实现(LinkedBag)
# 自定义单链表
class Node(object): # 定义一个单链表节点类
def __init__(self, data, next=None):
self.data = data
self.next = next
# 自定义双链表
class TwoWayNode(Node):
def __init__(self, data, previous=None, next=None):
Node.__init__(self, data, next)
self.previous = previous
# 基于单链表实现
class LinkedBag(object):
def __init__(self, sourceCollection=None):
self._items = None
self._size = 0
if sourceCollection:
for item in sourceCollection:
self.add(item)
def __len__(self):
return self._size
def __str__(self):
return '{'+' ,'.join(map(str, self))+'}'
def isEmpty(self):
return len(self) == 0
def __add__(self, other):
result = LinkedBag(self)
for item in other:
result.add(item)
return result
def __eq__(self, other):
if other is self:
return True
if type(self) != type(other) or len(self) != len(other):
return False
for item in self:
if not item in other:
return False
return True
def __iter__(self):
# 关键!!!迭代器
cursor = self._items # 将游标最初设置为外部指针 self._items,
while not cursor is None: # 在其为None时 停止循环
yield cursor.data # 提取当前节点的数据,
cursor = cursor.next # 指向下一个节点
def add(self, item):
self._items = Node(item, self._items)
self._size += 1
# don't check array memory
def clear(self):
self._size = 0
self._items = None
def remove(self,item):
probe = self._items
trailer = None
for targetItem in self:
if targetItem == item:
break
trailer = probe
probe = probe.next
# item 位于链表的头部节点,需要将这个节点指向next链接
if probe == self._items:
self._items = self._items.next
# item 位于第一个节点之后的某个节点,item上一个节点指向item的next节点
else:
trailer.next = probe.next
self._size -= 1
3. 继承ArrayBag类实现ArraySortedBag
新增 contains 方法,便于使用 in 运算符,最坏运行时间减少到 O(logn);
修改 add 方法,新增元素至排序数组的相应位置,但提高了时间复杂度;
修改 eq 方法,运行时间减少到 O(n)
from arraybag import ArrayBag
class ArraySortedBag(ArrayBag):
def __init__(self, sourceCollection=None):
ArrayBag.__init__(self, sourceCollection)
def __contain__(self, item):
""" 二叉搜索实现in操作符 """
left = 0
right = len(self) - 1
while (left <= right):
midPoint = (left + right) // 2
if self._items[midPoint] == item:
return True
elif self._items[midPoint] > item:
right = midPoint - 1
else:
left = midPoint + 1
return False
def add(self, item):
if self.isEmpty() or item >= self._items[len(self) - 1]:
ArrayBag.add(self, item)
else:
targetIdex = 0
while item > self._items[targetIdex]:
targetIdex += 1
for i in range(len(self), targetIdex, -1):
self._items[i] = self._items[i - 1]
self._items[targetIdex] = item
self._size += 1
def __eq__(self, other):
if self is other:
return True
if type(self) != type(other) or len(self) != len(other):
return False
for i in range(len(self)):
if self[i] != other[i]:
return False
return True
4. 抽象类AbstractBag
抽象类:类的通用特征和行为;不能正常的实例化;抽象冗余方法isEmpty, str, len, eq等
class AbstractBag(object):
"""抽象类:类的通用特征和行为;不能正常的实例化;抽象冗余方法isEmpty, str, len, eq等"""
def __init__(self, sourceCollection=None):
"""初始化冗余的方法"""
self._size = 0
if sourceCollection:
for item in sourceCollection:
self.add(item)
def __add__(self, other):
"""抽象不同的子类的add方法"""
result = type(self)(self)
for item in other:
result.add(item)
return result
def __len__(self):
return self._size
def __str__(self):
return '{'+' ,'.join(map(str, self))+'}'
def __eq__(self, other):
"""使用两个迭代器进行比较"""
if self is other:
return True
if type(self) != type(other) or len(self) != len(other):
return False
otherIter = iter(other)
for item in self:
if item != next(otherIter):
return False
return True
def isEmpty(self):
return len(self) == 0
转载请注明出处
参考书籍:《 数据结构(Python语言描述)》