线性表

  1. 顺序表
  2. 链接表

顺序表

在顺序表中,元素存储在一块大存储区中,元素间的逻辑顺序关系通过实际存储位置直接反映,元素存储位置可以基于下标算出。

在 Python 的官方实现中,list 是一种采用分离式技术实现的动态顺序表

list 操作的复杂度分析:

  • len() O(1) 操作
  • 特殊情况:表的尾端插入和删除是 O(1)
  • 一般位置(包括首端)的插入、删除、切片、替换、extend 都是 O(n)
  • clear() O(1)
  • reverse() O(n)
  • sort() O(nlogn)

链接表

不要求逻辑上相邻的两个元素物理上也相邻,通过“链”建立数据元素间的逻辑关系

插入、删除不需要移动数据元素,只需要修改“链”

注意:节点类的定义和链表类的定义一定要分清

链表操作的复杂度:

  • 创建空表 O(1)
  • 删除表 O(1)
  • 判断空表 O(1)
  • 首端加入 O(1)
  • 尾端加入 O(n): 需要遍历找出前面的一个节点(最后一个节点)
  • 定位加入 O(n): 同理
  • 首端删除 O(1)
  • 尾端删除 O(n)
  • 定位删除 O(n)

表的遍历

Python 语言为内部汇集(collection)类型提供的遍历机制是迭代器,关键字是 yield,标准使用方式是放在 for 语句头部

多重链表

链表中的节点可能同时隶属于多个链

  • 多重链表中节点的指针域会有多个
  • 但包含两个指针域的链表并不一定是多重链表,比如双向链表

树和图这种相对复杂的数据结构可以用多重链表方式实现

链表的变形和操作

单链表的简单变形

单链表:每个节点只有一个指针域

可以在类定义中引入表尾指针 self._rear

类设计的内在一致性:要采用同样的原则

复杂度分析:

  • 首端插入和删除 O(1)
  • 尾端插入 O(1)
  • 尾端删除 O(n) 由于节点只有指向下一个节点的指针域,表尾指针的前一个节点仍然需要遍历才能得出

循环单链表

只有表尾指针,表尾节点的下一个节点是链表的首节点

  • 首端插入和删除 O(1)
  • 尾端插入 O(1)
  • 尾端删除 O(n) 表尾指针的前一个节点仍然需要遍历才能得出

双链表(双向链接表)

表头指针和表尾指针

双向链接节点

复杂度分析:

  • 首端插入和删除 O(1) 表头指针
  • 尾端插入和删除 O(1) 表尾指针(能得到表尾指针的前一个节点)

链表操作

反转(reverse)

顺序表反转:用首尾两个下标,通过逐对交换元素位置并把下标向中间位置移动,直到两个下标碰头,操作完成

链接表反转

  • 双链表可以像顺序表那样操作,因为有表头表尾两个指针
  • 对于单链表,在表的首端删除和插入是 O(1) 复杂度

注意:当循环条件不容易确定时,可以用 while Ture:,再用 if...break 语句跳出循环

排序(sort)

[ ] 插入排序