数据类型决定数据在内存中所占用空间大小与从内存取出二进制数据时以什么类型对待
一体式结构与分离式结构的区别:
如果增加元素超过了列表的最大存储量时,则需要新建一个数据区
一体式结构若想更换数据区,则要整体更改;而分离式结构则只需要更改表信息区中的数据区链接地址即可.即该顺序表对象不变
list的基本实现技术
Python标准类型list就是一种元素个数可变的线性表,可以加入和删除元素,并在各种操作中维持已有元素的顺序(即保序),而且还具有以下行为特征:
基于下标(位置)的高效元素访问和更新,时间复杂度应该是O(1);
为满足该特征,应该采用顺序表技术,表中元素保存在一块连续的存储区中。
允许任意加入元素,而且在不断加入元素的过程中,表对象的标识(函数id得到的值)不变。
为满足该特征,就必须能更换元素存储区,并且为保证更换存储区时list对象的标识id不变,只能采用分离式实现技术。
在Python的官方实现中,list就是一种采用分离式技术实现的动态顺序表(允许存储区扩充的顺序表)。这就是为什么用list.append(x) (或 list.insert(len(list), x),即尾部插入)比在指定位置插入元素效率高的原因。
扩充问题
在Python的官方实现中,list实现采用了如下的策略:在建立空表(或者很小的表)时,系统分配一块能容纳8个元素的存储区;在执行插入操作(insert或append)时,如果元素存储区满就换一块4倍大的存储区。但如果此时的表已经很大(目前的阀值为50000),则改变策略,采用加一倍的方法。引入这种改变策略的方式,是为了避免出现过多空闲的存储位置。
python数据结构的例子
list和tuple两种类型采用了顺序表的实现技术
list是采用分离式结构,元素外置形式,倍数扩充的顺序表
顺序表python版的实现(部分功能未实现)
#!/usr/bin/env python
# -*- coding:utf-8 -*-
class SeqList(object):
def __init__(self, max=8):
self.max = max #创建默认为8
self.num = 0
self.date = [None] * self.max
#list()会默认创建八个元素大小的列表,num=0,并有链接关系
#用list实现list有些荒谬,全当练习
#self.last = len(self.date)
#当列表满时,扩建的方式省略
def is_empty(self):
return self.num is 0
def is_full(self):
return self.num is self.max
#获取某个位置的元素
def __getitem__(self, key):
if not isinstance(key, int):
raise TypeError
if 0<= key < self.num:
return self.date[key]
else:
#表为空或者索引超出范围都会引发索引错误
raise IndexError
#设置某个位置的元素
def __setitem__(self, key, value):
if not isinstance(key, int):
raise TypeError
#只能访问列表里已有的元素,self.num=0时,一个都不能访问,self.num=1时,只能访问0
if 0<= key < self.num:
self.date[key] = value #该位置无元素会发生错误
else:
raise IndexError
def clear(self):
self.__init__()
def count(self):
return self.num
def __len__(self):
return self.num
#加入元素的方法 append()和insert()
def append(self,value):
if self.is_full():
#等下扩建列表
print("list is full")
return
else:
self.date[self.num] = value
self.num += 1
def insert(self,key,value):
if not isinstance(key, int):
raise TypeError
if key<0: #暂时不考虑负数索引
raise IndexError
#当key大于元素个数时,默认尾部插入
if key>=self.num:
self.append(value)
else:
#移动key后的元素
for i in range(self.num, key, -1):
self.date[i] = self.date[i-1]
#赋值
self.date[key] = value
self.num += 1
#删除元素的操作
def pop(self,key=-1):
if not isinstance(key, int):
raise TypeError
if self.num-1 < 0:
raise IndexError("pop from empty list")
elif key == -1:
#原来的数还在,但列表不识别他
self.num -= 1
else:
for i in range(key,self.num-1):
self.date[i] = self.date[i+1]
self.num -= 1
def index(self,value,start=0):
for i in range(start, self.num):
if self.date[i] == value:
return i
#没找到
raise ValueError("%d is not in the list" % value)
#列表反转
def reverse(self):
i,j = 0, self.num - 1
while i<j:
self.date[i], self.date[j] = self.date[j], self.date[i]
i,j = i+1, j-1
if __name__=="__main__":
a = SeqList()
print(a.date)
#num == 0
print(a.is_empty())
a.append(0)
a.append(1)
a.append(2)
print(a.date)
print(a.num)
print(a.max)
a.insert(1,6)
print(a.date)
a[1] = 5
print(a.date)
print(a.count())
print("返回值为2(第一次出现)的索引:", a.index(2, 1))
print("====")
t = 1
if t:
a.pop(1)
print(a.date)
print(a.num)
else:
a.pop()
print(a.date)
print(a.num)
print("========")
print(len(a))
a.reverse()
print(a.date)
"""
print(a.is_full())
a.clear()
print(a.date)
print(a.count())
"""