写在前面
挺早之前看的数据结构和算法了,但是最近刷LeetCode上题目的时候发现还不是很熟练(都忘光了....),于是狠心再来一遍。边整理边刷题,用的教材是北大裘宗燕的《数据结构与算法python语言描述》和浙大陈越的《数据结构第二版》,结合参考网上一些大牛的博客,希望能比第一次看有收获吧~
1.线性表简介
- 定义:线性表是由同一类型的数据元素构成的有序序列的线性结构。表中元素个数称为线性表的长度 ;没有元素时,称为空表 ;表的起始位置称为表头,表的结束位置称为表尾。
- 表的抽象数据类型(ADT):
数据对象集:线性表是 n (≥0) 个元素构成的有序序列( a 1 , a 2 , ……,a n )
操作集:线性表L 属于 List ,整数i 表示位置,元素X 属于ElementType
- 线性表的操作:
| List(self) | 表构造操作,创建一个空表 |
| is_empty(self) | p按断是否为空表 |
| len(self) | 获得表的长度 |
| prepend(self,elem) | 将元素elem加入表中作为第一个元素 |
| append(self,elem) | 将元素elem加入表中作为最后一个元素 |
| insert(self,elem,i) | 将elem插入表中第i个位置 |
| del_first(self) | 删除表的首元素 |
| del_last(self) | 删除表的尾元素 |
| del(self,i) | 删除表中位置i的元素 |
| search(self,elem) | 查找elem在表中出现的位置,不出现时返回-1 |
| forall(self,op) | 对表中的每个元素执行操作op |
- 线性表的实现:
2.线性表的顺序存储实现(顺序表)
线性表的顺序存储是指在内存中用地址连续的一块存储空间顺序存放线性表的各个元素。
顺序表的python实现在我的Github上:顺序表结构python实现
3.线性表的链式存储实现
为了克服顺序表运行效率不高的情况,引入链式存储:将表元素存放在通过链接构造起来的一系列存储块里。
链接表有多种不同的组织方式。下面先讨论最简单的单链表,其中每个结点里记录着下一元素的结点的标识。后面将介绍一些变形。
单链表结点的形式如下,在单链表里,与表里的n 个元素对应的n 个结点通过链接形成一条结点链。从表里的任一个结点都可以找到保存下一个元素的结点。
下面介绍几个单链表操作:
- 加入元素
- 删除元素
单链表的Python实现传送门:单链表的python实现
4.链表的变形
虽然单链表的效率比顺序表优越,但是仍存在一些不足。针对其缺点进行改进后有如下几种形式的链表变形。
4.1 带尾结点引用的单链表
注意到前面单链表在尾端加入元素的操作效率低,而实际值可能经常需要往尾结点中加入元素,于是可以给表对象增加一个对表尾结点的引用,使得在尾段加入元素也能做到O(1)。
对于该链表的实现,可以继承单链表类,对于非变动操作(如is_empty,elements等)直接继承,对于变动操作(如首端和尾端删除插入等)需要重新定义。
带尾结点的单链表Python实现传送门:点击打开链接
4.2 循环单链表
循环单链表是单链表的另一种变形,其最后结点的next不是指向None,而是指向首结点。
循环单链表Python实现传送门:点击打开链接
4.3 双链表
单链表只有一个方向的连接,只能做一个方向的扫描和逐步操作。如果希望两端插入和删除操作都能高效完成,就必须修改结点的基本设计,加入另一个方向的链接。这样就得到了双向链接表,可以直接从当前结点找到前后结点。
双链表的Python实现传送门:点击打开链接
5.小结
- 基本单链表包含一系列结点,通过一个方向的链接构造起来。他支持高效的前端插入和删除,但对于定位和尾端操作都需要O(n)的时间。
- 增加了尾结点的单链表可以很好地支持首端、尾端插入和首端弹出操作,但不能支持高效的尾端删除
- 循环单链表也能支持高效的首端、尾端插入和首端弹出操作,在这种表上扫描,要注意结束判断问题
- 双链表每个结点都有两个方向的链接,因此可以高效地找到前后结点。如果有尾结点引用,两端插入和删除操作能在O(1)时间内完成
优点:
- 表结构是通过一些链接起来的结点形成的,结构很容易调整修改
- 不修改结点里的数据元素,只通过修改链接,就能灵活地修改表的结构和内容。如加入/删除一个或多个元素,翻转整个表,重排元素的顺序,将一个表分解为两个或多个等
- 整个表由一些小存储块构成,较容易安排和管理(不是我们的事)
缺点,一些操作的开销大:
- 基于位置找到表中元素需要线性时间
- 尾端操作需要线性时间(增加尾指针可以将尾端加入元素变为常量操作,但仍不能有效实现尾端删除)
- 找当前元素的前一元素需要从头扫描表元素(双链表可以解决这个问题,但每个结点要付出更多存储代价),应尽量避免
以上~
2018.04.25