1. 顺序表: max=9 num=5 [1,2,3,4,5, , , , ] 优点: 1. 元素存储紧凑,节省空间,除表元素外,只需要O(1)空间存储辅助信息max,num 2. 查找速度快,通过下标进行快速定位 缺点: 1. 需要连续的存储区域,如果表很大就需要很大片的连续内存空间,如果很大的存储区只保存少量数据,会造成存储浪费 2. 执行加入和删除时,会移动很多元素,效率低 3. 创建表时需要考虑存储大小,而实际需求很难事先估计 分离式存储: 元素和辅助信息max,num分开存储,表空间不足时,把表复制到更大的空间实现扩展存储 python为防止空间浪费,创建空表时分配8个元素的存储区域,如果表满就换一个4倍大的区域,如果表储存区域>=50000,则改变策略向系统申请 2倍大的区域,引入后一种策略是为了防止空间浪费 实现: 开一块内存,依次存入,逻辑关系通过存储区的物理位置表示 实例tuple: 按元素个数分配内存,创建不变的顺序表,例如python中的tuple (1,2,3) 实例list: 创建表时预留一些空位,前面存放元素,后面留空位,便于扩展;前面存放存储区大小,和当前元素个数,随时更新 尾端加入新元素append: 根据num值添加元素,即可实现append 中间添加insert: 新元素放入后将原元素添加到尾部(非保序) 新元素放入后原元素依次后移一位(保序) 尾端删除元素: num减1即可, 索引不到即为删除 2. 单链表: 掌握一个单链表,只要掌握这个表的首节点即可,从它出发,根据链接即可找到表里所有的数据元素 [head 表头指针]->[1]->[2]->[3]->[4]->……->[表尾 None] 优点: 不必向系统申请整块内存空间,随意扩展,存储空间不连续 缺点: 存储密度小,每个节点都增加了一个链接域,增加的空间开销与节点数成正比O(n) 创建空链表: 申请一个内存区域,将表头变量设置为None,时间复杂度O(1) 删除链表: 在python中只需把表指针赋值为None,即可抛弃所有链表节点,解释器会自动回收不用的内存空间,时间复杂度O(1) 判断是否为空链表: 判断表头值是否为None,时间复杂度O(1) 判断链表是否满: 一般而言链表不会满,除非用完了所有可用的存储空间 表头插入元素: 申请新内存存入元素,改变表头索引到新内存head,新内存next索引到原头部,如下图,时间复杂度O(1) [head]->[10]->[1]->[2] 其他位置插入元素: 改变索引即可,时间复杂度O(n) 删除表头元素: 将表头指针指向第二个元素节点即可,废弃节点由python解释器回收,时间复杂度O(1) 删除表尾元素: 找到要删除元素的前一节点,改变next指向,时间复杂度O(n),因为即使增加了表尾引用域,也无法倒序找到前一元素的next,只能遍历整表 删除其他位置元素: 找到要删除元素的前一节点,改变next指向,时间复杂度O(n) 扫描定位遍历: 遍历整个表,时间复杂度O(n) 单链表的高效列表反转算法: 因为单链表的首端增删操作都是O(1),所以只需要不断的从原表首端取下节点,将其插入另一个表的首端,即可完成反转,时间复杂度O(n) 单链表的简单变形: 1. 求表的长度,遍历全表O(n)时间复杂度会成为效率问题,可以改变单链表的实现结构,增加一个表长度记录,这个记录不属于任何表 元素,每次表的变动操作都需要维护计数值,求表长度时,直接返回该值,整体来看有得有失,O(1)时间内得到表长度,牺牲表操作时间 2. 表对象增加尾部节点引用域,这样既可在O(1)时间内找到尾节点,表尾加入新元素的操作也可做到O(1),代价是表变动,值实时维护 3. 循环单链表,把最后一个节点的next域不用None,而是指向表的第一个节点,这样就成了环,哪个节点算是表头或表尾主要是概念问题 3. 双链表: 1. 在单链表的基础上增加另一方向的链接,也就是一个元素需要两个链接域,增加灵活性,牺牲空间,这样就得到了双向链接表 2. 也可以增加尾部引用,高效访问和操作表尾元素 3. 将表首尾相连就得到了循环链表(圆) <-[head]<-->[1]<-->[2]<-->[3]<-->[4]<-->……<-->[None]-> 优点: 1. 增加尾部引用后,两端高效操作,一般节点的操作也会更加方便,从双链表的任一节点出发,可以找到其前后相邻节点,时间复杂度O(1) 2. 灵活修改表结构和数据排列方式,只需要修改节点之间的链接即可 3. 不需要大存储块,方便安排和管理,python解释器负责 缺点: 存储密度小, 每个节点都增加了一个链接域, 增加的空间开销与节点数成正比O(n) 双链表的元素删除: 如果有尾节点引用,首尾两端元素的加入/删除时间复杂度都是O(1),直接改变元素前后链接即可 改变元素顺序: 修改节点链接关系,通过修改节点的链接顺序来改变表元素的顺序 扫描定位遍历: 可以从表头或表尾开始,遍历整个表, 时间复杂度O(n) 循环链表的遍历: 可以从表中任一元素开始,但是要注意结束条件 4. 链表的缺点: 整体来看双链表的缺点是空间占用,优点是灵活性 1. 定位需要挨个遍历,需要线性时间O(n),顺序表直接通过下标定位O(1) 2. 增加尾部指针后,尾部访问为O(1),删除操作需要定位到节点的next,双链表可以高效操作首尾,但牺牲了空间 3. 要找到当前元素的前一元素,需要遍历整表,双链表可解决这个问题,但牺牲了空间 4. 双链表提高了操作灵活性,但需要两个链接域,使用二分法前后两端同步查找可提高一倍速度,如何抉择看时间和空间如何平衡 浅谈单链表与双链表的区别: 浅谈单链表与双链表的区别_kangxidagege的博客-优快云博客_单链表和双链表的区别
python 数据结构
于 2019-01-28 17:25:24 首次发布