美文网首页
02_链表link_list

02_链表link_list

作者: 蕴重Liu | 来源:发表于2019-07-14 03:26 被阅读0次

概念:链表是通过指针关联的链式结构

注意:列表 list 底层是线性结构

单链表

--操作复杂度
linked_list.append(value)   O(1)
linked_list.appendleft(value)   O(1)
linked_list.find(value) O(n)
linked_list.remove(value)   O(n)

class Node(object):
    def __init__(self, value=None, next=None):
        self.value = value
        self.next = next

    def __str__(self):
        return '<None:value: {}, next = {}>'.format(self.value,self.next)

    __repr__ =  __str__

class LinkedList(object):
    def __int__(self, maxsize=None):
        self.maxsize = maxsize
        self.root = Node()
        self.tailnode = None
        self.length = 0

    def __len__(self):
        return self.length

    def append(self, value):
        if self.maxsize is not None and len(self) >= self.maxsize:
            raise Exception('LinkedList is Full')
        node = Node(value)
        tailnode = self.tailnode
        if tailnode is None:
            self.root.next = node
        else:
            tailnode.next = node
        self.tailnode = node
        self.length += 1

    def appendleft(self, value):
        if self.maxsize is not None and len(self) >= self.maxsize:
            raise Exception('LinkedList is Full')
        node = Node(value)
        if self.tailnode is None:
            self.tailnode = node
        headnode = self.root.next
        self.root.next = node
        node.next = headnode
        self.length += 1

    def __iter__(self):
        for node in self.iter_node():
            yield node.value

    def iter_node(self):
        """遍历从head到tail节点"""
        curnode = self.root.next
        while curnode is not self.tailnode:
            yield curnode
            curnode = curnode.next
        if curnode is not None:
            yield curnode

    def remove(self, value):
        prevnode = self.root
        for curnode in self.iter_node():
            if curnode.value == value:
                prevnode.next = curnode.next
                if curnode is self.tailnode:    # 更新 tailnode
                    self.tailnode = prevnode
                del curnode
                self.length -= 1
                return 1  # 表明删除成功
            else:
                prevnode = curnode
        return -1  # 表明删除失败

    def find(self, value):
        index = 0
        for node in self.iter_node():
            if node.vallue == value:
                return index
            index += 1
        return -1  #没找到

    def popleft(self):
        """删除第一个链表节点"""
        if self.root.next is None:
            raise Exception('pop from empty LinkedList')
        headnode = self.root.next
        self.root.next = headnode.next
        self.length -= 1
        value = headnode.value

        if self.tailnode is headnode:
            self.tailnode = None
        del headnode
        return value

    def clear(self):
        for node in self.iter_node():
            del node
        self.root.next = None
        self.length = 0
        self.tailnode = None

    def reverse(self):
        """反转列表"""
        curnode = self.node.next
        self.tailnode = curnode
        prevnode = None

        while curnode:
            nextnode = curnode.next
            curnode.next = prevnode
            if nextnode is None:
                self.root.next = curnode
            prevnode = curnode
            curnode = nextnode

def test_liked_list():
    ll = LinkedList()
    ll.append(0)
    ll.append(1)
    ll.append(2)
    ll.append(3)

    assert len(ll) == 4
    assert ll.find(2) == 2
    assert ll.find(-1) == -1

    assert ll.remove(0) == 1
    assert ll.remove(10) == -1
    assert ll.remove(2) == 1
    assert len(11) == 2
    assert list(11) == [1, 3]
    assert ll.find(0) == -1
    ll.append(0)
    assert list(11) == [0, 1, 3]
    assert len(11) == 3

    headvalue = ll.popleft()
    assert headvalue == 0
    assert len(ll) == 2
    assert list(11) == [1, 3]

    assert ll.popleft() == 1
    assert list(11) == [3]
    ll.popleft()
    assert len(ll) == 0
    assert ll.tailnode is None

    ll.clear()
    assert len(ll) == 0
    assert list(ll) == []


def test_linked_list_remove():
    ll = LinkedList()
    ll.append(3)
    ll.append(4)
    ll.append(5)
    ll.append(6)
    print(list(ll))


def test_linked_list_append():
    ll = LinkedList()
    ll.appendleft(1)
    ll.append(2)
    assert  list(ll) == [1, 2]


if __name__ == '__main__':
    test_liked_list()
    test_linked_list_remove()
    test_linked_list_append()

双链表

--操作复杂度
cdll.append(value)  O(1)
cdll.appendleft(value)  O(1)
cdll.remove(node),注意这里参数是 node  O(1)
cdll.headnode() O(1)
cdll.tailnode() O(1)
class Node(object):
    __slots__ = ('value', 'prev', 'next')

    def __init__(self, value=None, prev=None, next=None):
        self.value, self.prev, self.next = value, prev, next

class CircularDoubleLinkedList(object):
    '''
    循环双端链表
    多了个循环 把root的prev指向tail节点,串起来
    '''
    def __init__(self, maxsize=None):
        self.maxsize = maxsize
        node = Node()
        node.next, node.prev = node, node
        self.root = node
        self.length = 0

    def __len__(self):
        return self.length

    def headnode(self):
        return self.root.next

    def tailnode(self):
        return self.root.prev

    def append(self, value):
        if self.maxsize is not None and len(self) >= self.maxsize:
            raise Exception('LinkedList is Full')
        node = Node(value=value)
        tailnode = self.tailnode() or self.root

        tailnode.next = node
        node.prev = tailnode
        node.next = self.root
        self.root.prev = node
        self.length += 1

    def appendleft(self, value):
        if self.maxsize is not None and len(self) >= self.maxsize:
            raise Exception('LinkedList is Full')
        node = Node(value=value)
        if self.root.next is self.root:
            node.next = self.root
            node.prev = self.root
            self.root.next = node
            self.root.prev = node
        else:
            node.prev = self.root
            headnode = self.root.next
            node.next = headnode
            headnode.prev = node
            self.root.next = node
        self.length += 1

    def remove(self, node):
        '''
        在lru_cache 里实际根据key保存整个node
        '''
        if node is self.root:
            return
        else:
            node.prev.next = node.next
            node.next.prev = node.prev
        self.length -= 1
        return node

    def iter_node(self):
        if self.root.next is self.root:
            return
        curnode = self.root.next
        while curnode.next is not self.root:
            yield curnode
            curnode = curnode.next
        yield curnode

    def __iter__(self):
        for node in self.iter_node():
            yield node.value

    def iter_node_reverse(self):
        '''相比单链独有的反序遍历'''
        if self.root.prev is self.root:
            return
        curnode = self.root.prev
        while curnode.prev is not self.root:
            yield curnode
            curnode = curnode.prev
        yield curnode

def test_double_link_list():
    dll = CircularDoubleLinkedList()
    assert len(dll) == 0
    dll.append(0)
    dll.append(1)
    dll.append(2)

    assert list(dll) == [0, 1, 2]
    assert [node.value for node in dll.iter_node()] == [0, 1, 2]
    assert [node.value for node in dll.iter_node_reverse()] == [2, 1, 0]

    headnode = dll.headnode()
    assert headnode.value == 0
    dll.remove(headnode)
    assert len(dll) == 2
    assert [node.value for node in dll.iter_node()] == [1, 2]

    dll.appendleft(0)
    assert [node.value for node in dll.iter_node()] == [0, 1, 2]

if __name__ == '__main__':
    test_double_link_list()

相关文章

  • 02_链表link_list

    概念:链表是通过指针关联的链式结构 注意:列表 list 底层是线性结构 单链表 双链表

  • 02_单向循环链表[Python]

    1. 简介 单链表的一个变形是单向循环链表,链表中最后一个节点的下一个域不再为无,而是指向链表的头节点。 2. 操...

  • 学习HM微博项目第4天

    步骤:OAuth授权01_加载登录界面 -> OAuth授权02_获得accessToken -> OAu...

  • 立裁   课堂分享一廓形衬衫02..成品

    立裁 课堂分享一廓形衬衫02_成品 小芳同学作品一棉麻面料

  • 链表基础

    链表基础 链表长度 链表为空 链表结构 链表增加

  • 双向链表&双向循环链表

    链表分为:单链表、单向循环链表、双向链表、双向循环链表本节主要说明:双向链表、双向循环链表 定义结点 一、双向链表...

  • 02_ webstrom

    在webstrom 中设置node 安装目录 ========================= Module b...

  • 09_使用SDL播放PCM

    通过命令ffpay播放PCM 可以使用ffplay播放《08_音频录制02_编程[https://www.jian...

  • 算法与数据结构:链表

    链表 链表还分为单向链表和双向链表, 但是这篇文章只说单向链表 , 下次再讲双向链表 . 链表和数组的区别 ? 链...

  • 链表

    链表 单链表反转链表中环的检测两个有序链表合并删除链表倒数第n个节点求链表的元素总个数 一.单向链表 链表共有特征...

网友评论

      本文标题:02_链表link_list

      本文链接:https://www.haomeiwen.com/subject/eayukctx.html