1. 首页
  2. Python

python之路—–列表

 
内建常用数据结构
  • 序列sequence
    • 字符串str,字节序列bytes,bytearray
    • 列表list,元祖tuple
  • 键值对
    • 集合set,字典dict
 
线性数据结构
  • 线性表(简称表),是一种抽象的数学概念,是一组元素序列的抽象,它由任意个元素组成。
  • 顺序表:使用一大块连续的内存顺序存储表中的元素,这样实现的表称为顺序表,或称连续表。
在顺序表中,元素的关系使用顺序表的存储顺序自然的表示。
链接表:在存储空间中将分散存储的元素链接起来,这种实现称为链接表,简称链表。
 
列表 有序,可以插队、离队,可以索引
链表 有序但随意,可插队、离队,也可索引
 
列表list
  • 一个整齐排队的队伍,python采用顺序表实现
  • 列表中的个体称为元素,由若干个元素组成列表
  • 元素可以是任意对象(数字,字符串,对象,列表)
  • 列表内的元素有顺序,可以使用索引
  • 是一种线性数据结构
  • 使用[]表示
  • 列表是可变的
 
列表初始化
list1 = []
list2 = list()   #这两个是空列表
list3 = list(range(5))  #从range对象中把所有拿到的值组建一个标识符为list3的新列表
 
列表中必须写可迭代对象
 
索引
索引,也叫下标;
正索引:从左至右,从0开始,为列表中每一个元素编号
如果列表有元素,,索引范围[0,长度-1]
复索引:从右至左,从-1开始
正负索引不可以越界
我们简单认为列表是从左至右排列的,左边是头部(下界),右边是尾部(上界)
列表通过索引访问,list[index],index就是索引,使用中括号访问
 
使用索引定位访问元素的时间复杂度为O(1),这是最快的方式,是列表最好的使用方式
 
 
查询
  • index(value,[start,[stop]])
    • 通过value值,从指定区域查找列表内的元素是否匹配
    • 匹配到第一个值就立即返回索引;匹配不到,就抛出异常ValueError
list=[1,2,3,4,2,1]
list.index(2) —> 返回值是1
list.index(2,3) —>返回值是4 #查找2这个值,从第3个索引开始
  • count(value)
    • 返回列表中匹配到value的次数
时间复杂度:
index和coint方法都是O(n) ,这两种方法都需要遍历列表,随着列表数据规模的增大,查询的效率下降。
 
 
修改
索引定位元素,然后修改,索引不能越界
list[index]=value
ls1=[1,2,3,4,5]
ls1[2]=6
ls1 = [1.2.6.4.5]
 
增加
  • 增加单个元素:
    • append(object)-> None #推荐使用
列表尾部增加元素,返回none,意味着没有新的列表产生,就地修改。
定位时间复杂度是O(1),效率高
    • insert(index,object) -> None
在指定的索引inde处(当前索引前)插入元素object,一次插入一个数据返回none,意味着没有新的列表产生,就地修改,时间复杂度是O(n),效率低
list.append(value)
ls1=[1,2,3] ls1.append(5) —> ls1=[1,2,3,5]
ls1.insert(2,0) —> ls1=[1,2,0,3,5]
#在第2个索引位置增加值为0的对象
注意:
  • 增加元素时,索引可以越界:
超越上界,尾部追加,相当于append在尾部追加
超越下界,头部追加,相当于在索引0处,插入到队首
  • 列表是容器,python中列表可以自动扩大,会先给初始大小,不够一般会自动扩增2倍,扩容是耗时的,如果连续内存空间够,没问题,如果不够,会涉及到垃圾回收,这样效率就慢了。
 
  • 增加多个元素(成批扩展):
    • list.extend()
list=[1,2,3,]
list.extend(range(10,50,10)) —> list=[1,2,3,10,20,30,40]
list.extend([7,8,9]) —> list=[1,2,3,7,8,9]
以上两种方法都是就地尾部扩展
 
  • + *
+ 把两个列表拼接组合在一起,产生一个全新的列表,原列表不变
* 将给定列表的元素重复n次,生成全新的列表
list1+list2=newlist
list1=[1,2,3]
lsit1*3 —> list=[1,2,3,1,2,3,1,2,3]
*把指定列表里的所有元素重复3次,形成新列表
 
删除
  • remove(value) ->None
从左至右查找第一个匹配value值,找到就已出该值,并返回none,就地修改
因为需遍历列表,定位时间复杂度是O(n),移除掉指定元素之后,其后所有元素向前挪动,效率极差。特别是在队首移除时,效率最低。
list=[1,2,3] list.remove(3) —> list=[1,2]
  • pop(index) -> 弹出被删除的值
使用索引定位快,但是移除元素后,其余元素挪动,效率一样低
pop() 不加index,表示从尾部移除最后一个元素,效率高
  • clear() -> None
清除列表所有元素,剩下一个空列表
 
 
反转
  • reverse() -> None
将列表元素反转,返回none,就地修改
 
排序
  • sort() -> None
对列表元素进行就地排序,默认升序,一般是在同类型间进行比较
list=[1,3,8,2] list.sort() list=[1,2,3,8]
使用reverse为True,表示反转,降序
list=[1,3,8,2] list.sort(reverse=True) list=[8,3,2,1]
使用key函数,指定key如何排序
list=[1,3,8,2,’abc’] list.sort(key=str) list=[1,2,3,8,’abc’]
#str转换后的值,只用来比较,决定先后次序,并不影响输出
 
in成员操作
list=[1,3,8,2] 3 in list True —> 返回值为bool类型
for i in list: 经常使用的循环赋值语句
 
列表复制
  • 浅拷贝,也叫影子拷贝
a=[1,2,3] b=a.copy()
a == b #b指向到了a的引用地址,此时a和b的元素相同 True
a is b #本质是在问是不是同一个对象 False ; is比较内存地址,使用copy之后,两个列表只是内容相同,但实际上是存在于内存中的id不同的两个个体。
具体的原理如下:
浅拷贝不管多复杂,只copy第一层,两表内第一层数据改变,不会影响对方,但深层次的数据改变都会影响到对方;b拷贝a表时,只拷贝了第一层的数据,但更深层次的数据,b表只拷贝了a表的一个内存引用地址,当a或b表改变了引用地址中的值,由于a b都指向同一个引用地址,所有值都相等;
 
  • 深拷贝
深拷贝就是在内存中重新开辟一块空间,不管数据结构有多复杂,都把所有内容复制下来,直到最后一层,相当于定义了一个新的变量,各自有自己的内存地址,数据不会相互影响,因为内存不共享。深拷贝是完全拷贝,数据变化只影响自己身。
python之路-----列表
 
 
常见线性结构比较
1、链接表增加、删除元素的效率高么?
如果定位数据是遍历index,O(n),找到后,插入或删除元素,都是先断开手,再重新牵手。遍历的过程效率不高,链表的头尾操作效率更高。
 
元素规模较大,增删频繁,尽量使用链接表;如果是尾部操作,顺序表、链表都行。
 
链接表改、查、遍历元素的效率,都不高。O(n),因为都需要遍历列表,随着列表的规模增加,耗时增加。
 
2、stark栈:先进后出,在效率上,列表、链接表都行。
      queue队列:有栏杆,不能插队,不能离队,只能首尾操作
            先进先出,使用链表,队首,手断开,不挪动,性能很高。
           后进先出,列表、链接表都行。
 
 
 
在python中,一切皆对象,对象都是引用类型,可理解为一个地址指针指向这个对象
 
O(1),与列表规模n关,数据增加,性能不变
O(n),与列表规模n关,数据增加,性能变差
 

原创文章,作者:wz,如若转载,请注明出处:https://www.wzstyle.cn/357.html

发表评论

邮箱地址不会被公开。 必填项已用*标注