Python 实现双向链表(容器化)

双向链表

设计思路

  • 整体设计分为两个类, 一个是节点类, 每个节点作为一个对象; 另一个是链表类, 根据相邻节点间关系(上一个可以找到下一个, 下一个可以找到上一个, head 节点和 tail 节点为 None), 实现对各个节点间关系的操作, 包括append, insert, pop, remove等
  • 第二阶段将设计好的类封装成容器
  • 整体代码看似复杂, 实际理解发现并非如此, 理清节点间关系就好啦 …

class ListNode:
    def __init__(self, item, next=None, prev=None):
        self.item = item
        self.next = next
        self.prev = prev

    def __repr__(self):
        return "{} <== {} ==> {}".format(
            self.prev.item if self.prev else None,
            self.item,
            self.next.item if self.next else None
        )

class LinkedList:
    def __init__(self):
        self.head = None
        self.tail = None

    def append(self, item):
        node = ListNode(item)
        if self.head is None:
            self.head = node
        else:
            self.tail.next = node
            node.prev = self.tail

        self.tail = node
        return self

    def insert(self, index, item):
        if index < 0:
            raise IndexError

        current = None
        for i, node in enumerate(self.iternodes()):
            if i == index:
                current = node
                break
        else:
            self.append(item)
            return

        # break 找到
        node = ListNode(item)
        prev = current.prev
        next = current

        if i == 0:  # 开头
            self.head = node
        else:   # 不是开头
            prev.next = node
            node.prev = prev
        node.next = next
        next.prev = node

    def pop(self):  # 尾部移除
        if self.tail is None:   # 空
            raise Exception

        node = self.tail
        item = node.item
        prev = node.prev

        if prev is None:    # 仅一个元素
            self.head = None
            self.tail = None
        else:
            prev.next = None
            self.tail = prev

        return item

    def remove(self, index):
        if self.tail is None:
            raise Exception

        if index < 0:
            raise IndexError

        current = None
        for i, node in enumerate(self.iternodes()):
            if i == index:
                current = node
                break
        else:
            raise IndexError

        prev = current.prev
        next = current.next

        # 4 种情况
        if prev is None and next is None: # 1个节点
            self.head = None
            self.tail = None
        elif prev  is None: # 头
            self.head = next
            next.prev = None
        elif next is None: # 尾
            self.tail = prev
            prev.next = None
        else: # 中间
            prev.next = next
            next.prev = prev

        del current

    def iternodes(self, reverse=False):
        current = self.tail if reverse else self.head
        while current:
            yield current
            current = current.next if not reverse else current.prev

改进

## 容器化

class ListNode:
    def __init__(self, item, next=None, prev=None):
        self.item = item
        self.next = next
        self.prev = prev

    def __str__(self):
        return "{} <== {} ==> {}".format(
            self.prev.item if self.prev else None,
            self.item,
            self.next.item if self.next else None
        )

    __repr__ = __str__

class LinkedList:
    def __init__(self):
        self.head = None
        self.tail = None
        self._size = 0

    def append(self, item):
        node = ListNode(item)
        if self.head is None:
            self.head = node    # 开头节点
        else:
            self.tail.next = node   # 更新当前tail 节点的next
            node.prev = self.tail

        self.tail = node    # 设置新tail

        self._size += 1
        return self     # 链式编程

    def insert(self, index, item):
        # if index < 0:
        #     raise IndexError
        #
        # current = None
        # for i, node in enumerate(self.iternodes()):
        #     if i == index:
        #         current = node
        #         break
        # else:
        #     self.append(item)
        #     return

        if index >= len(self):
            self.append(item)
            return

        if index < -len(self):
            index = 0

        current = self[index]

        # break 找到
        node = ListNode(item)
        prev = current.prev
        next = current

        if prev == None: # 开头
            self.head = node
        else:   # 不是开头
            prev.next = node
            node.prev = prev
        node.next = next
        next.prev = node

        self._size += 1

    def pop(self):  # 尾部移除
        if self.tail is None:   # 空
            raise Exception

        node = self.tail
        item = node.item
        prev = node.prev

        if prev is None:    # 仅一个元素
            self.head = None
            self.tail = None
        else:
            prev.next = None
            self.tail = prev

        self._size -= 1
        return item

    def remove(self, index):
        if self.tail is None:   # 空链表
            raise Exception

        # if index < 0:
        #     raise IndexError
        #
        # current = None
        # for i, node in enumerate(self.iternodes()):
        #     if i == index:
        #         current = node
        #         break
        # else:
        #     raise IndexError

        current = self[index]

        prev = current.prev
        next = current.next

        # 4 种情况
        if prev is None and next is None: # 1
            self.head = None
            self.tail = None
        elif prev  is None: # 头
            self.head = next
            next.prev = None
        elif next is None: # 尾
            self.tail = prev
            prev.next = None
        else:
            prev.next = next
            next.prev = prev

        del current
        self._size -= 1

    def iternodes(self, reverse=False):
        current = self.tail if reverse else self.head
        while current:
            yield current
            current = current.next if not reverse else current.prev

    size = property(lambda self: self._size)

    # 容器化
    def __len__(self):
        return self._size

    # def __iter__(self):
    #     yield from self.iternodes()
    __iter__ = iternodes

    def __reversed__(self):     # 解决reversed 内建函数调用
        return self.iternodes(True)

    def __getitem__(self, index):
        if index >= len(self) or index <= -len(self):
            raise IndexError
        reverse = False if index >= 0 else True
        start = 0 if index >= 0 else 1

        for i, node in enumerate(self.iternodes(reverse), start):
            if i == abs(index):
                return node

    def __setitem__(self, index, value):
        self[index].item = value


ll = LinkedList()
ll.insert(0, 'start')
ll.insert(1000, 'end')

for x in ll:
    print(x)

print('-' * 30)
print(ll[1], len(ll))
print()
for x in reversed(ll):
    print(x)

运行结果

None <== start ==> end
start <== end ==> None
------------------------------
start <== end ==> None 2

start <== end ==> None
None <== start ==> end
False
------------------------------
None <== start~~~~ ==> end
start~~~~ <== end ==> None
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值