python种List的底层实现

我们都知道我们用的python一般都是Cpython,就是说底层是C语言写的,本文是对链接的学习

List对象的结构

typedef struct {
    Pyobject_VAR_HEAD;
    Pyobject **ob_item;
    Py_ssize_t allocated;
}PyListObject;

我们可以看到里面的元素是二级指针,list名是一级指针,里面的元素也是指针,也就是说list中的元素其实是一个个的指针,指针指向真正的数据

这也就是为什么python的list可以添加任意类型的元素,另外allocated是ob_item预先分配的内存总容量


List的初始化,L = []会发生什么

arguments: size of the list = 0
returns: list object = []
PyListNew:
    nbytes = size * size of global Python object = 0
    allocate new list object
    allocate list of pointers (ob_item) of size nbytes = 0
    clear ob_item
    set list's allocated var to 0 = 0 slots
    return list object

list实际申请内存空间的大小和list实际存储元素所占空间的大小之间的关系要理解,ob_size和len(L)是一样的,而allocated(申请内存空间的大小)的大小是在内存中已经申请空间大小。通常情况下allocated的值要比ob_size的值要大,为了避免每次有新元素加入list时都要调用realloc进行内存分配


调用append

arguments: list object, new element
returns: 0 if OK, -1 if not
app1:
    n = size of list
    call list_resize() to resize the list to size n+1 = 0 + 1 = 1
    list[n] = list[0] = new element
    return 0

上面我们已经说了要避免经常调用realloc,这里也就是list_resize,要申请多余的空间防止多次调用list_resize函数

每次内存不够的增长模型在c++的vector中是每次容量是上次的2倍

但是这里的增长模型是:0, 4, 8, 16, 25, 35, 46, 58, 72, 88, …

(如何确立这种模型是需要进行大量数据分析来选择合适的模型)

一个指针数组,指向数值1


 

insert:


list_resize

arguments: list object, new size
return s: 0 if OK, -1 if not
list_resize:
    new_allocated = (newsize >> 3) + (newsize < 9 ? 3 : 6)
    new_allocated += newsize = 3+1 = 4
    resize ob_item(list of pointers) to size new_allocated
    return 0

pop

list.pop会弹出最后一个元素,调用listpop(),list_resize在函数listpop内部被调用,因为弹出某个元素后可能ob_size小于allocated已经分配的内存空间的一半,则需要对申请的内存空间缩小

arguments: list object
returns: element popped
listpop:
    if list empty:
        return null
    resize list with size 
    set list object size to xx
    return last element
//pop的时间复杂度O(1)

 复杂度为O(1):


remove

python list对象有一个方法可以移除一个指定的元素。调用listremove

arguments: list object, element to remove
returns none if OK, null if not
listremove:
    loop through each list element
    if correct element:
        slice list between element's slot and element's slot + 1
        return none
    return null

切开list和删除元素,调用了list_as_slice()

arguments: list object, low offset, high offset
returns: 0 if OK
list_ass_slice:
    copy integer 5 to recycle list to dereference it
    shift elements from slot 2 to slot 1
    resize list to 5 slots
    return 0
//时间复杂度为O(n)

复杂度为O(n):

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值