链接列表在迭代中如何更快?使用__iter__和__next__或__getitem__?

时间:2015-09-16 20:15:05

标签: python performance linked-list

我基本上试图通过以下链接列表来模拟python列表的一些特性:

class List:

    def __init__(self):
        self.head = None
        self.tail = None
        self.length = 0

    def append(self, value):
        node = Node(value)
        if not self.head:
            self.head = self.tail = node
        else:
            tail = self.tail
            tail.next = node
            self.tail = node
        self.length += 1

    def __len__(self):
        return self.length

    def __getitem__(self, i):
        if i >= len(self):
            raise IndexError("Index out of range.")
        elif i < len(self):
            index = 0
            current = self.head
            while index <= i:
                if index == i:
                    return current
                current = current.next
                index += 1

    def __contains__(self, value):
        for node in self:
            if value == node.value:
                return True
        return False

class Node:

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

所以我需要使这个链表尽可能高效,特别是在循环遍历它的一个大实例时。有没有办法改进我的 getitem 实现或替代使用 iter next 来最大化性能而不使用任何类型的python& #39;内置数据结构,例如列表或元组?如果有人能提出任何代码示例,我将不胜感激。

3 个答案:

答案 0 :(得分:2)

这会稍微有效一些,因为它摆脱了一些变量赋值和比较。

def __getitem__(self, i):
    if i >= len(self):
        raise IndexError("Index out of range.")

    current = self.head
    for _ in xrange(i):
        current = current.next

    return current

但是,链接列表上的随机访问始终至少为O(n)。如果您不是在寻找随机访问而是纯粹的迭代,__iter__是可行的方法,因为使用__len____getitem__的组合进行迭代将是O(n^2),这是非常可怕你可以这样做:

def __iter__(self):
    current = self.head

    while current:
        yield current
        current = current.next

您不必提供任何__next__next方法。 yield从方法中就足够了。

答案 1 :(得分:0)

定义__iter__:返回一个保持对当前节点的引用的迭代器。然后它可以获得O(1)中的下一个节点。 __getitem__遍历O(n)中的请求节点。

答案 2 :(得分:0)

定义__iter__方法:

def __iter__(self):
    current = self.head
    while current:
        yield current
        current = current.next