数据结构与算法 | 双向链表

# CY3761 | 2021-12-15 20:58

import types
import copy


# 链表的节点可以通过 头尾进行找下一个或者上一个
# A => prev item next
# B => prev item next
# C => prev item next
# A.next = B
# B.prev = A B.next = C
# C.prev = B

class Node:
    def __init__(self, _item, **kwargs):
        self.item = _item  # 当前节点值
        self.prev = self.next = None
        
        if kwargs.get('prev'):  # 指向上一个节点
            self.prev = kwargs.get('prev')
        
        if kwargs.get('next'):  # 指向下一个节点
            self.next = kwargs.get('next')


class DoubleChain:
    def __init__(self):
        self.head = None  # 链表头
        self.leng = 0  # 链表长度
        
        pass
    
    def isEmpty(self):
        return self.leng <= 0
        pass
    
    def items(self, isItem=False):
        items = []
        
        aItem = self.head
        while aItem:
            items.append(aItem)
            aItem = aItem.next
        
        if isItem:
            return [_.item for _ in items]
        return items
    
    def before(self, item):
        # A => prev item next
        # self.head = A, self.leng = 1
        # B => prev item next | B, A
        # self.head = B, self.leng = 2 | B.next = A, A.prev = B
        # C => prev item next | C, B, A
        # self.head = C, self.leng = 3 | C.next = B, B.prev = C
        # ...
        node = Node(item)
        
        if self.isEmpty():
            self.head = node
        else:
            node.next = self.head
            
            self.head.prev = node
            self.head = node
        
        self.leng += 1
        
        pass
    
    def after(self, item):
        # A => prev item next
        # self.head = A, self.leng = 1
        # B => prev item next | A, B
        # self.head = A, self.leng = 2 | A.next = B, B.prev = A
        # C => prev item next | A, B, C
        # self.head = A, self.leng = 3 | B.next = C, C.prev = B
        # ...
        node = Node(item)
        
        if self.isEmpty():
            self.head = node
        else:
            foot = self.head
            while foot.next:  # 这里必须 aItem.next
                foot = foot.next
            foot.next = node  # 原尾节点.next = 新节点
            node.prev = foot  # 新节点.prev = 原尾节点
            
            pass
        
        self.leng += 1
    
    def where(self, pos, item):  # 不需要改变
        pos = int(pos)
        
        if pos <= 0:
            return self.before(item)
        elif pos >= self.leng:
            return self.after(item)
        else:
            # A, C, ...
            # self.head = A, self.leng = 3
            # 1 B => prev item next | A, B, C,
            # A.next = B, B.prev = A, B.next = C, C.prev = B
            # self.leng = 4
            
            print('-' * 80)
            print(item)
            
            item = Node(item)  # 新建节点
            nItem = self.head  # 后一个节点
            pItem = nItem  # 前一个节点
            
            # 找插入位置的 前一个和后一个
            while pos > 0:
                pItem = nItem
                nItem = nItem.next
                pos -= 1
            
            print(pItem, pItem.item)
            print(nItem, nItem.item)
            
            item.prev = pItem  # 新节点.prev = 前一个节点
            item.next = nItem  # 新节点.next = 后一个节点
            pItem.next = item  # 前一个节点.next = 新节点
            nItem.prev = item  # 后一个节点.prev = 新节点
            
            self.leng += 1
    
    def remove(self, item):
        """
            找到删除值
            删除值的前一个的next = 删除值的后一个
            删除值的后一个的prev = 删除值的前一个
            
            删除值的next = 删除值的prev = None
        """
        aItem = self.head
        
        while aItem:
            if aItem.item == item:
                if aItem == self.head:  # 是头节点
                    self.head = aItem.next
                else:
                    aItem.prev.next = aItem.next
                
                if aItem.next:
                    aItem.next.prev = aItem.prev
                
                self.leng -= 1
                return 0
            aItem = aItem.next
        
        return -1
        pass
    
    def update(self, pos, item):
        pos = int(pos)
        
        if 0 > pos > self.leng:
            return -1
        
        aItem = self.head
        
        while pos > 0:
            aItem = aItem.next
            pos -= 1
        
        aItem.item = item
        
        pass
    
    # 查找指定值的节点是否存在
    def search(self, item):
        aItem = self.head  # A
        isHas = False
        while aItem:
            if aItem.item == item:
                isHas = True
                break
            
            aItem = aItem.next
        
        return 1 if isHas else -1


def eachDoubleChain(args, method, methodString, chain=None):
    if chain is None:
        a = DoubleChain()
    else:
        a = chain
    print('-' * 80)
    print(a.leng, a.items(True))
    
    if not isinstance(method, types.LambdaType):
        raise Exception('method not is LambdaType')
    
    for _ in args:
        b = method(a, _)
        
        print(_, b, a.leng, methodString.format(*_), a.items(True))
    
    return a


if __name__ == '__main__':
    eachDoubleChain([
        'A', 'B', 'C', 'D', 'E'
    ], lambda a, _: a.before(_), 'a.before({})')
    
    b = eachDoubleChain([
        'A', 'B', 'C', 'D', 'E'
    ], lambda a, _: a.after(_), 'a.after({})')
    
    c = eachDoubleChain([
        (0, 'a'), (2, 'b'), (4, 'c'), (6, 'd'), (8, 'e')
    ], lambda a, _: a.where(*_), 'a.where({},{})', b)
    d = copy.deepcopy(c)
    
    eachDoubleChain([
        'A', 'B', 'C', 'D', 'E'
    ], lambda a, _: a.remove(_), 'a.remove({})', c)
    
    c = eachDoubleChain([
        (0, '一'), (4, '二'), (1, '三'), (2, '四'), (3, '五')
    ], lambda a, _: a.update(*_), 'a.update({},{})', d)
    
    eachDoubleChain([
        '一', '二', '三', '四', '五'
    ], lambda a, _: a.search(_), 'a.search({})', c)

在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CY3761

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值