Python 里面的链表与传统的 list 之间的差别

系统 1695 0
            
              import time


def log_time(func, *args, **kwargs):
    def inner():
        t1 = time.time()
        func(*args, **kwargs)
        t2 = time.time()
        print(f"使用的时间是{t2 - t1}s")
    return inner


@log_time
def append_func():
    ll = list()
    for i in range(10000):
        ll.append(i)


@log_time
def insert_func():
    ll = list()
    for j in range(10000):
        ll.insert(0, j)


insert_func()
append_func()

            
          

通过以上程序说明 python 中 list 的 append 要快于 insert。

其实, Python 中的 list 并不是传统(计算机科学)意义上的列表。传统的列表,也叫做链表(Linked List),通常是由一系列的节点来实现的,其每个节点(尾节点除外)都有一个指向下一个节点的引用。
使用 python 实现一个链表的节点类如下:

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

            
          

接下来,我们就可以用其实现一个列表了:

            
              # L 即一个链表的头节点
L = Node("a", Node("b", Node("c", Node("d"))))
print(L.value)
print(L.next.value)
print(L.next.next.value)
print(L.next.next.next.value)

            
          

这是一个所谓的单向列表,双向列表的各节点里面还有持有一个指向前一个节点的引用。但是 python 中的 list 则于此有点不同,它不是由若干个独立的节点相互引用形成的,而是一整块单一连续的内存块 —— 我们通常称之为数组(array)。这直接导致了它和链表之间的一些重要的区别。

如果我们想要按照既定的索引值对某元素进行直接访问的话,显然使用数组会更加有效率。因为在数组中,我们可以直接计算出目标元素在内存中的位置,并且能对其进行直接访问,而对于链表来说,我们必须从头开始访问整个链表。

而如果我们想要进行 insert 操作,对于链表来说,只要知道了在哪里执行 insert 操作,其操作成本是非常低的。无论其中有多少个元素,其操作时间大致上是相同的。而数组就非常不一样了,它在每次执行 insert 的时候都需要移动插入点右边的所有元素,甚至在必要时,我们还需要将这些列表元素整体搬到一个更大的数组中。也正是因为如此,append 操作通常采用一种被称为动态数组或者是向量的特定解决方案。其主要想法是将内存分配得大一点,并且等到其溢出时,在线性时间内再次重新分配内存。

这样做似乎会使得 append 和 insert 一样糟糕,其实不然,因为尽管这两种情况都有可能迫使我们去搬动大量的元素,但是主要的不同点在于,对于 append 操作,发生这样的可能性要小得多。事实上,如果我们能确保所搬入的数据都大过原来数据一定的比例(例如 20% 甚至 100%),那么该操作的平均成本(或者说得更加确切一些,将这些搬运开销均摊单每次 append 操作中去)通常是常数的。
我们可以认为,对于 python 中的 list 而言,append n 个数字所需要的运行时间是 O(n), 而在首端 insert 相同数量的数字需要的时间约为 O(n^2)。

更新时间: 2019.9.6
参考:《python 算法教程》


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论