• 双向链表


    链表是实现了数据之间保持逻辑顺序,但存储空间不连续的数据结构。
    相对于单向链表,双向链表多了一个指向前面一个节点的指针域。
    链表查询效率较慢,因为查询的时候需要移动指针一个一个找。
    双向链表新增和删除元素效率较高,因为链表会记录前一个节点和后一个节点。

    class Node:
        def __init__(self, item, next=None, prev=None):
            self.item = item
            self.next = next
            self.prev = prev
    
        def __str__(self):
            return '<prev: {} <- node: {} -> next: {}>'.format(self.prev.item if self.prev else None, self.item, self.next.item if self.next else None)
    
        def __repr__(self):
            return str(self.item)
    
    class LinkedList:
        def __init__(self):
            self.head = None
            self.tail = None
            self.size = 0
    
        def append(self, item):
            node = Node(item)
            # 如果head节点为空,表示链表为空
            if self.head is None:
                self.head = node
                self.tail = node
            else:
                self.tail.next = node
                node.prev = self.tail
                self.tail = node
            self.size += 1
            return self
    
        def index(self, item):
            for i, node in enumerate(self):
                if item == node.item:
                    return i
            else:
                raise ValueError('item does not exist')
    
        def insert(self, index, item):
            if index < 0:
                raise IndexError
    
            # 如果找到就将current指向对应位置的节点,继续后面的操作
            # 如果没有找到(链表为空或者索引超界),则追加并立即返回,后面的操作将不会执行
            for i, node in enumerate(self):
                if i == index:
                    current = node
                    break
            else:
                self.append(item)
                return
    
            node = Node(item)
            prev = current.prev
    
            # 从头部插入
            if prev is None:
                node.next = current
                current.prev = node
                self.head = node
            # 从中间插入(尾部插入即追加,上面已经实现)
            else:
                node.next = current
                node.prev = prev
                prev.next = node
                current.prev = node
    
            self.size += 1
    
        def pop(self):
            # 如果尾部为空,则表示链表为空
            if self.tail is None:
                raise Exception('empty')
    
            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 index < 0:
                raise IndexError('does not support negative index')
    
            # 如果链表为空,则抛出异常
            if self.head is None:
                raise Exception('empty')
    
            # 如果找到就将current指向对应位置的节点,继续后面的操作
            # 如果没有找到(链表为空或者索引超界),则抛出异常
            for i, node in enumerate(self):
                if i == index:
                    current = node
                    break
            else:
                raise IndexError('index out of range')
    
            prev = current.prev
            next = current.next
    
            # 如果current没有前节点也没有后节点,表示只有一个节点
            if prev is None and next is None:
                self.head = None
                self.tail = None
            # 如果不止一个节点,且如果current没有前节点,表示current是head
            elif prev is None:
                next.prev = None
                self.head = next
            # 如果不止一个节点、current不是head,且如果current没有后节点,表示current是tail
            elif next is None:
                prev.next = None
                self.tail = prev
            # 剩下就是多节点从中间remove的情况
            else:
                prev.next = next
                next.prev = prev
    
            self.size -= 1
    
        # def iternodes(self, reverse=False):
        #     current = self.head if not reverse else self.tail
        #     while current:
        #         yield current
        #         current = current.next if not reverse else current.head
    
        def clear(self):
            for node in self:
                node.prev = None
                node.tail = None
            self.head = None
            self.tail = None
            self.size = 0
    
        def __iter__(self):
            current = self.head
            while current:
                yield current
                current = current.next
    
        def __reversed__(self):
            current = self.tail
            while current:
                yield current
                current = current.prev
    
        def __len__(self):
            # current = self.head
            # count = 0
            # while current:
            #     count += 1
            #     current = current.next
            # return count
            return self.size
    
        def __getitem__(self, key):
            # 支持负索引
            obj = reversed(self) if key < 0 else self
            start = 1 if key < 0 else 0
    
            for i, node in enumerate(obj, start):
                if abs(key) == i:
                    return node
            else:
                raise IndexError('index out of range')
    
        def __setitem__(self, key, value):
            # for i, node in enumerate(self):
            #     if key == i:
            #         node.item = value
            # else:
            #     self.append(value)
            self[key].item = value
    
    
    linklist = LinkedList()
    
    # 测试append()
    for i in range(10):
        linklist.append(i)
    
    # 测试__iter__
    for node in linklist:
        print(node)
    
    # 测试__reversed__
    for node in reversed(linklist):
        print(node)
    
    # 测试__len__
    print(len(linklist))
    
    # 测试index()
    print(linklist.index(3))
    
    # 测试insert()
    linklist.insert(0, 0)
    print(list(linklist))
    
    # 测试pop()
    print(linklist.pop())
    
    # 测试__getitem__
    print(linklist[3])
    # print(linklist[13])
    print(linklist[-1])
    
    # 测试__setitem__
    linklist[5] = 15
    print(list(linklist))
    
    # 测试clear()
    linklist.clear()
    print(list(linklist))
    print(len(linklist))
    

    参考:
    http://zhaochj.github.io/2016/05/12/2016-05-12-数据结构-链表/
    https://blog.csdn.net/qq_26118603/article/details/79039738
    http://blog.suchasplus.com/2011/03/why-python-Standard-library-does-not-implement-the-list.html
    https://www.zhihu.com/question/55721190

  • 相关阅读:
    真题演练3
    牛客挑战赛43. C.最优公式 (二分,思维,切比雪夫距离与曼哈顿距离的转换)
    F. Equal Product (数学,思维,暴力)
    BJOJ 4402 Claris的剑 (组合数学,思维)
    牛客.二分图染色 (组合数学,思维,递推)
    树 (DP,dfs序,组合数学,思维)
    牛客练习赛69 E.子串 (树状数组, 思维)
    牛客练习赛14 B.区间的连续段 (倍增)
    城市网络(树上倍增)
    D. Game of Pairs (构造,思维)
  • 原文地址:https://www.cnblogs.com/keithtt/p/9711039.html
Copyright © 2020-2023  润新知