数据结构与具体数据类型:集合数据的内部表示
最长用来实现集合的两种数据结构:数组、链表
数组:可以在给定索引位置访问/替代项的一个序列(长度/容量在创建时就已固定)
Python列表的底层数据结构就是数组,array模块包含array类,仅限存储数字
创建新的Array类以保存任何类型的项
可见,数组是列表的一个非常受限的版本
随机访问和连续内存
数组索引是一个随机的访问操作,因此无论数组大小,访问第一项和最后一项所需的时间相同
数组索引步骤:
1 获取数组内存块的基本地址
2 给这个地址加上索引,返回最终结果
常量时间的随机访问功能要求数组必须用一段连续的内存来表示
动态数组在运行时并不需要知道动态数组的长度(Array类,借助列表)
物理大小和逻辑大小
物理大小 | 数组单元的总数(创建数组时指定其容量的数字) |
逻辑大小 | 可供应用程序使用的项的数目 |
作用:
1 逻辑大小为0,数组为空 ---> 该数组不包含数据项
2 在任意给定时间,数组中最后一项的索引都是其逻辑大小减去1
3 逻辑大小=物理大小,则数组已经被数据填满了
数组的操作(自己编写)
1 增加数组的大小(逻辑大小=物理大小,插入新项时需要)
1.1 创建一个更新的、更大的数组
1.2 将数组从旧数据复制到新数组中
1.3 将旧的数组变量重新设置为新的数组对象
旧数组的内存留给了垃圾回收程序
(自然增加,长度增加一个单位以容纳新项,但是整体性能是O(n^2))
2 减小数组的大小(未使用的单元>=某个阈值)
2.1 创建一个新的更小的数组
2.2 旧数组数据复制到新数组中
2.3 旧数组变量重新设置为新数组对象
这一操作允许在减少数组大小的时候浪费一些内存
3 在数组中插入一项
3.1 先检查可用空间
3.2 从数组的逻辑结尾开始直到目标索引位置,每一项都后移一个单位
3.3 将新的项赋值给目标索引的值
3.4 逻辑大小+1
移动项的时间性能在平均情况下是线性的
4 在数组中删除一项
4.1 从目标索引位置后一位开始,到数组的逻辑结尾,将每一项向前移动一位
4.2 将逻辑大小-1
4.3 检查物理空间,有必要则-1
装载因子等于数组中存储的项的数目/数组的容量
二维数组(网格)
计算table所有元素的和
已有一个用于二维数组的Grid类,创建Grid对象,三个参数(高度,宽度,最初填充值)
class Grid(object):
def __init__(self, rows, columns, fillValue=None):
self._data = Array(rows)
for row in range(rows):
self._data[row] = Array(columns, fillValue)
def getHeight(self):
return len(self._data)
def getWidth(self):
return len(self._data[0])
def __getitem__(self, index):
return self._data[index]
def __str__(self):
result = ''
for row in range(self.getHeight()):
for col in range(self.getWidth()):
result += str(self._data[row][col]) + ' '
result += '\n'
return result