Python数据结构与算法(2):接口、实现、多态、继承与抽象

接口、实现、多态、继承与抽象

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语言描述)》

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值