Python实现双向链表容器化

双向链表

  • Data 数据 + Next 指针 + Prev 指针,组成一个双向链表的内存结构;
  • 第一个内存结构称为 链头,最后一个内存结构称为 链尾;
  • 链头的 Prev 指针设置为 NULL, 链尾的 Next 指针设置为 NULL;
  • Prev 指向的内存结构称为 前驱, Next 指向的内存结构称为 后继;
  • 双向链表的遍历是双向的,即如果把从链头的 Next 一直到链尾的[NULL] 遍历方向定义为正向,那么从链尾的 Prev 一直到链头 [NULL ]遍历方向就是反向;
class  Node: # 定义双向链表的元素结点类
    def __init__(self, datap, prev=None, nextval=None):
        self.datap = datap
        self.prev = prev # 表示前一个指针
        self.nextval = nextval # 表示后一个指针
    
    def __repr__(self): # 为了方便查看,这里选择打印出完整的Node,而不只是datap数据项
        return "{}<={}=>{}".format(
        self.prev.datap if self.prev else None,
        self.datap,
        self.nextval.datap if self.nextval else None)
    
#     def __repr__(self):
#         return "{}".format(self.datap)
        
class DoubleLinkedList: # 定义一个链表类
    def __init__(self, datap=None):  # 双向链表的初始化  
        if datap:
            self.head = Node(datap)
            self.tail = self.head
            self.len = 1
        else:
            self.head = None
            self.tail = None
            self.len = 0
    
    def append(self, value): # 尾部追加
        node = Node(value) # 每次操作前,先生成一个Node的实例对象
        if not self.head:
            self.head = node
            self.tail = node
            self.len += 1
        else: # 此处的逻辑至关重要
            self.tail.nextval = node
            node.prev = self.tail
            self.tail = node
            self.len += 1
            
    def appendleft(self, value): # 头部追加
        node = Node(value)
        if not self.head:
            self.head = node
            self.tail = node
            self.len += 1
        else:  # 逻辑同append相反,千万谨慎  
            self.head.prev = node
            node.nextval = self.head
            self.head = node
            self.len += 1
    
    def __iter__(self): # 迭代链表所有的datap,这个方法至关重要!
        curser = self.head
        while curser:
            yield curser # yield出去的是一个Node结点,这才是完整的链表  
            if curser == self.tail:
                break
            curser = curser.nextval
            
    def __len__(self): # 查看链表长度
        return self.len

    def index(self, value): # 根据一个值查找索引,约定为正向第一个匹配值
        current = self.head
        for i, node in enumerate(self): # 遍历当前链表
            if node.datap == value:
                return i
                break
        else:
            raise ValueError("{} not in DoubleLinkedList".format(value))
                
    
    def __getitem__(self, index): #索引,正向和负向索引都可以  
        if index >= self.len or index < -self.len:
            raise IndexError("DoubleLinkedList index out of range")  
        
        for i, node in enumerate(self):
            if i == index or i == self.len + index:
                # return v.datap # 不应该返回数据,而是返回链表上的一个元素...
                return node

    def __setitem__(self, index, value): # 索引并替换掉当前位置的值
        self[index].datap = value
        
    def insert(self, index, value): # 在指定位置处插入值,无边界
        if index <= 0:
            self.appendleft(value)
        elif index >= self.len:
            self.append(value)
        else:
            nextnode = self[index]
            prevnode = self[index].prev
            node = Node(value)
            node.nextval = nextnode
            node.prev = prevnode
            prevnode.nextval = node
            nextnode.prev = node
            self.len += 1
    
    def remove(self, value): # 删除当前链表的第一个value值
        if self.head is None: # 
            raise ValueError("{} not in DoubleLinkedList".format(value))
        else:
            for i, node in enumerate(self): # 遍历链表
                if node.datap == value: # 满足匹配的
                    if self.len == 1: # 长度为1的情况
                        self.head = None
                        self.tail = None
                        self.len -= 1
                        break
                    else: 
                        if node == self.head: # 去掉链头
                            self.head = node.nextval
                            self.head.prev = None
                            self.len -= 1
                            break
                        elif node == self.tail:  # 去掉链尾
                            self.tail = node.prev
                            self.tail.nextval = None
                            self.len -= 1
                            break
                        else:  # 去掉链中  
                            prevnode = node.prev
                            nextnode = node.nextval
                            prevnode.nextval = nextnode
                            nextnode.prev = prevnode
                            self.len -=1 
                            break
            else:
                raise ValueError()
    
    def delet(self, index):  # 根据索引删除值,可以负索引,写法和remove略有不同
        if self.head is None: # 
            raise ValueError("{} not in DoubleLinkedList".format(value))
        if index >= self.len or index < -self.len:
            raise IndexError("DoubleLinkedList index out of range")  
        
        for i, node in enumerate(self): # 寻找满足要求的Node
            if i == index or i == self.len + index: 
                current = node

        prevnode = current.prev
        nextnode = current.nextval
        if self.len == 1:  # 只有一个Node
            self.head = None
            self.tail = None
            self.len -= 1
        elif prevnode is None: # 去掉的是链头
            self.head = nextnode
            nextnode.prev = None
            self.len -= 1
        elif nextnode is None: # 去掉的是链尾
            self.tail = prevnode
            prevnode.nextval = None
            self.len -= 1
        else:  # 去掉的是链的中间node  
            prevnode.nextval = nextnode
            nextnode.prev = prevnode
            self.len -= 1
    
    def pop(self): # 默认删除尾部最后一个node
        if self.head is None:
            raise IndexError(": pop from empty DoubleLinkedList")
        elif self.len == 1:
            self.head = None
            self.tail = None
            self.len -= 1
        else:
            self.tail = self.tail.prev
            self.tail.nextval = None
            self.len -= 1
    
    def popleft(self): # 删除最左边
        if self.head is None:
            raise IndexError(": pop from empty DoubleLinkedList")
        elif self.len == 1:
            self.head = None
            self.tail = None
            self.len -= 1
        else:
            self.head = self.head.nextval
            self.head.prev = None
            self.len -= 1
    
#     def reverse(self): # 就地反转,实现了__getitem__和__len__就实现了就地反转  
#         pass
    
    def __repr__(self): # 可视化打印
        return "{}".format([i for i in self])
        
        
        def con:
            if x in self:
            
    
l1 = DoubleLinkedList(1)
l1.append(2)
for i in reversed(l1):
    print(i.datap)
for i in l1:
    print(i.datap)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值