python数据结构学习笔记(五)
- 5 Array-Based Sequence
- 5.2.1 referential arrays
- 5.2.2 compact arrays in python
- array.array
- 5.3 dynamic arrays and amortization
- 5.3.1 implementing a dynamic array
- 5.4 efficiency of python's sequence types
- constant-time operation
- 字符串拼接
- 5.6 multidimensional data sets
5 Array-Based Sequence
5.2.1 referential arrays
数组在内存中是连续的地址单元,而且每个单元的大小是相同的。对于python的list来说,里面可以存储不同长度的 字符串或者其他元素,为了存下最长的那个字符串,list必须给每个单元很大的空间,这样实际上有很多单元只利用 了小部分的存储,内存的利用率很低。实际上,python的list中每个单元只存储了一个对象的引用,相当于 只保存了它的地址,这样所有对象的地址都是统一长度的.list中空的位置的引用指向None对象
5.2.2 compact arrays in python
string是字符数组,这与一般的list不同,list中存储的是引用,而string中是直接存储字符,所以可以说是 紧密的
的数组。如果string中存储的是unicode,则每个字符需要2bytes的空间。
与紧密数组相比,普通list需要更多的空间,比如我们想要存储一百万个64-bit整数,我们希望每个整数只使用64 bits 来存储。实际上我们需要在数组中给每个整数存储一个64位地址的引用,另外每个int类型在python中是14byte,所以 实际上每个整数用了18bytes来存储。
array.array
from array import array
primes = array('i', [2,3,5,7])
array函数提供紧密数组,其中'i'代表integers,array()函数第一个参数是里面元素的类型。
python中的ctype模块里提供了类似c语言中的紧密数组。
5.3 dynamic arrays and amortization
创建一个低级的紧密数组的时候,必须声明数组的大小,因为系统必须给数组分配连续的内存空间。
python中的list类则提供了一种可动态扩展的数组,比如可以随时增加一个元素。在创建一个list的时候,实际上会 比它现在的长度分配多一点空间,用来给新增加的元素。如果原来预留的空间都使用完了,则list会重新向系统申请 新的空间,新的空间又比现在所有存储的元素预留多一些空间。这种做法就跟螃蟹成长的过程不断换壳一样。
len(list)可以获取当前list里面存的元素个数,但不是系统真正分配给list的内存。sys.getsizeof(list)
可以 list真正的bytes。
import sys
data = []
for k in range(n):a = len(data)b = sys.getsizeof(data)print "length: {0:3d}; size in types: {1:4d}".format(a,b)data.append(None)
结果如下:
Length: 0;size in bytes: 72
Length: 1;size in bytes: 104
Length: 2;size in bytes: 104
Length: 3;size in bytes: 104
Length: 4;size in bytes: 104
Length: 5;size in bytes: 136
...
可以发现初始化一个空数组时已经分配了72bytes的空间,后面不断增加元素之后每次增加32bytes。
5.3.1 implementing a dynamic array
要实现动态增长的数组,我们可以先用一个固定数组a来存储,当a满的时候,创建更大的数组b,先使得b[i]=a[i], 然后将a指向b,这时候就可以插入新的元素了。如何确定新数组b的容量比较合适?一种做法是取b的容量刚好是a的2倍
import ctypesclass DynamicArray:"""a dynamic array class like a simplified python list"""def __init__(self):self._n = 0self._capacity = 1self._A = self._make_array(self._capacity) # low-level arraydef __len__(self):return self._ndef __getitem__(self, k):if not 0 <= k < self._n:raise IndexError('invalid index')return self._A[k]def append(self, obj):if self._n == self._capacity:self._resize(2 * self._capacity)self._A[self._n] = objself._n += 1def _resize(self, c):"""resize internal array to capacity c"""B = self._make_array(c)for k in range(self._n):B[k] = self._A[k]self._A = Bself._capacity = cdef _make_array(self, c):return (c * ctypes.py_object)()
5.4 efficiency of python's sequence types
- tuple: nonmutating
- list
constant-time operation
返回序列的长度只需要常数时间,因为序列中维护有这一信息可以直接返回。同样是常数时间的有下标访问data[i]
字符串拼接
如要把文档中的所有字母字符取出组成一个字符串, bad code:
letters = ''
for c in document:if c.isalpha():letters += c
这段代码是非常低效的。因为string类型是immutable
的,每次执行letters += c,都要重新创建一个string,然后 对letters重新赋值,而每次创建一个字符串的时间与该字符串长度成线性关系,所以总共需要1+2+...+n = O(n*n)的时间。
一种改进的方法是使用一个list代替string拼接,最后再一次性拼接给string,时间是O(n)
temp = []
for c in document:if c.isalpah():temp.append(c)
letters = ''.join(temp)
注意最后一行''.join(temp)只需要n的时间
实际上即使是每次对list进行append操作,虽然摊还时间是O(1),但是仍然可能需要多次动态扩建list,效率不如下面这种 使用comprehension syntax理解性语法。
letters = ''.join([c for c in document if c.isalpha()])
或者连创建list的过程都不需要
letters = ''.join(c for c in document if c.islpha())
因为string是immutable的,所以很多时候要对string进行操作的时候可以先讲string转化为list,然后对其进行修改, 操作完成之后再重新赋值给string。string转为list方式如list('bird')
可以得到['b', 'i', 'r', 'd']. 反过来list转为string则可以通过''.join(['b','r','i','d'])
5.6 multidimensional data sets
二维数组通常也叫矩阵。python中可以用嵌套的list来实现。
创建二维矩阵的一个错误方法如data = ([0] * c ) * r
,因为结果还是一个一维矩阵。
改进一下,用data = [[0] * 3] * 2
来创建2 * 3矩阵,得到结果[[0,0,0],[0,0,0]],好像满足要求。 但实际上这样做还不行,因为里面的两个list实际上指向同一个list,修改其中一个会导致两个都同时改变。
为了使里面的每个子list都是相互独立的,可以使用理解性语法来创建这样的二维list。 data = [[0] * c for j in range(r)]
转载于:https://www.cnblogs.com/jolin123/p/4632516.html
python数据结构学习笔记(五)相关推荐
- Python数据结构学习笔记——链表:无序链表和有序链表
目录 一.链表 二.无序链表 实现步骤分析 三.无序链表的Python实现代码 四.有序链表 实现步骤分析 五.有序链表的Python实现代码 结语 一.链表 链表中每一个元素都由为两部分构成:一是该 ...
- Python数据结构学习笔记——队列和双端队列
目录 一.队列的定义 二.队列 实现步骤分析 三.队列的Python实现代码 四.队列的应用 六人传土豆游戏 五.双端队列的定义 六.双端队列 实现步骤分析 七.双端队列的Python实现代码 八.双 ...
- Python数据结构学习笔记——栈
目录 一.栈的定义和特性 (一)栈的定义 (二)栈的反转特性 二.实现分析步骤 三.栈的Python实现代码 四.栈的应用 (一)匹配圆括号 (二)匹配符号 (三)模2除法(十进制转二进制) (四)进 ...
- Programming Computer Vision with Python (学习笔记五)
SciPy库 SciPy库,与之前我们使用的NumPy和Matplotlib,都是scipy.org提供的用于科学计算方面的核心库.相对NumPy,SciPy库提供了面向更高层应用的算法和函数(其实也 ...
- Python数据结构学习笔记——树和图
目录 一.树的概念 二.二叉树的实现 (一)列表的列表 (二)结点与引用 三.图的概念 四.图的实现 (一)邻接矩阵 (二)邻接表 一.树的概念 树是一种数据结构,树由结点及连接结点的边组成,每个树有 ...
- Python数据结构学习笔记——搜索与排序算法
目录 一.搜索 (一)搜索的方法 (二)顺序搜索 (三)二分搜索 二.排序 内排序和外排序 (一)冒泡排序 (二)选择排序 (三)插入排序 (四)希尔排序 (五)归并排序 (六)快速排序 总结 一.搜 ...
- 【Python】学习笔记五:缩进与选择
Python最具特色的用缩进来标明成块的代码 缩进 i = 4 j = 2 if i > j:i = i+1print(i) 这是一个简单的判断,Python的if使用很简单,没有括号等繁琐语法 ...
- python函数是一段具有特定功能的语句组_Python学习笔记(五)函数和代码复用
本文将为您描述Python学习笔记(五)函数和代码复用,具体完成步骤: 函数能提高应用的模块性,和代码的重复利用率.在很多高级语言中,都可以使用函数实现多种功能.在之前的学习中,相信你已经知道Pyth ...
- 数据结构学习笔记(五):重识字符串(String)
目录 1 字符串与数组的关系 1.1 字符串与数组的联系 1.2 字符串与数组的区别 2 实现字符串的链式存储(Java) 3 子串查找的简单实现 1 字符串与数组的关系 1.1 字符串与数组的联系 ...
最新文章
- Web 开发最有用的 jQuery 插件集锦
- [ARM-assembly]-Thumb指令集快速参考卡
- 绿色版本Tomcat
- layui根据name获取对象_layui表格行合并;解决侧边固定栏合并
- SAP License:SAP委外加工业务
- Java获取网络IP
- 多线程总结之旅(9):线程同步之事件
- wago edz 下载_用电子枪制造的WeakAuras Wago.io桥
- ALTER TABLE 语句与 FOREIGN KEY 约束“FK_Booking_Hotel“冲突。
- Navicat安装及pj
- 浅析向上转型和向下转型
- 基础练习 时间转换(给定一个以秒为单位的时间t,要求用“<H>:<M>:<S>”的格式来表示这个时间。<H>表示时间,<M>表示分钟,而<S>表示秒,它们都是整数且没有前导的“0”。例如,若t=0,)
- sofa-bolt(网络通信框架)
- 20200829 tektronix TPS 2024 示波器 compactflash设置
- socket 通讯 案例 详解
- MAC安装homebrew及使用
- C# 如何使用倒计时
- oracle安装时怎样调整sga,深入讲解调整Oracle SGA大小的解决方法
- vue改变element-ui 表格第一行或某一行样式
- 第7章——罗杰斯:自我实现理论