美文网首页
python 链表

python 链表

作者: 落羽归尘 | 来源:发表于2019-09-19 08:19 被阅读0次

简介

链表属于链式结构,内存是不连续的,链表中每个节点都会有指针指向下一个节点。通常一个链表有head节点,不存储数据。链表有不同的类型:

  • 单链表:单向的,每个节点有一个数据块,一个指针,指向下一节点。
  • 双向链表:双向的,每个节点有两个节点,一个指向前驱节点,一个指向后驱节点。

链表的优点:

  • 插入和删除速度快,时间复杂度O(1)。而数组是O(n)
  • 内存利用率高,易动态扩展

链表的缺点:

  • 查找速度慢,时间复杂度O(n)。而数组是O(1)

单链表的python实现

  • 先定义节点类,value属性用于保存值,next属性指向下一个节点。
class Node(object):
    def __init__(self, value=None, next=None):
        self.value = value
        self.next = next
  • 单链表类:
class LinkedList(object):
    """ 链接表 ADT
    [root] -> [node0] -> [node1] -> [node2]
    """

    def __init__(self, maxsize=None):
        """
        :param maxsize: int or None, 如果是 None,无限扩充
        """
        self.maxsize = maxsize
        self.root = Node()     # 默认 root 节点指向 None
        self.tailnode = None
        self.length = 0

    def __len__(self):
        return self.length

    def append(self, value):    # O(1)
        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:    # 还没有 append 过,length = 0, 追加到 root 后
            self.root.next = node
        else:     # 否则追加到最后一个节点的后边,并更新最后一个节点是 append 的节点
            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:  # 如果原链表为空,插入第一个元素需要设置 tailnode
            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):    # O(n)
        """ 删除包含值的一个节点,将其前一个节点的 next 指向被查询节点的下一个即可
        :param value:
        """
        prevnode = self.root    #
        for curnode in self.iter_node():
            if curnode.value == value:
                prevnode.next = curnode.next
                if curnode is self.tailnode:  # NOTE: 注意更新 tailnode
                    self.tailnode = prevnode
                del curnode
                self.length -= 1
                return 1  # 表明删除成功
            else:
                prevnode = curnode
        return -1  # 表明删除失败

    def find(self, value):    # O(n)
        """ 查找一个节点,返回序号,从 0 开始
        :param value:
        """
        index = 0
        for node in self.iter_node():   # 我们定义了 __iter__,这里就可以用 for 遍历它了
            if node.value == value:
                return index
            index += 1
        return -1    # 没找到

    def popleft(self):    # O(1)
        """ 删除第一个链表节点
        """
        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:   # 勘误:增加单节点删除 tailnode 处理
            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.root.next
        self.tailnode = curnode  # 记得更新 tailnode,多了这个属性处理起来经常忘记
        prevnode = None

        while curnode:
            nextnode = curnode.next
            curnode.next = prevnode

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

            prevnode = curnode
            curnode = nextnode

相关文章

网友评论

      本文标题:python 链表

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