数据结构Python版——顺序表
Posted Iareges
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构Python版——顺序表相关的知识,希望对你有一定的参考价值。
目录
一、什么是线性表?
线性表就是数据元素的排列像一条线一样的表。线性表严格的定义是具有相同特性的数据元素组成的一个有限序列。其特征有3个:
- 所有元素的数据类型相同;
- 线性表是由有限个元素构成的;
- 线性表中的元素与位置相关,即每个元素都有唯一的序号(或索引)。
不同于集合,线性表中可以出现值相同的元素。
线性表的逻辑结构一般表示为 ( a 0 , a 1 , ⋯ , a n − 1 ) (a_0,a_1,\\cdots,a_n-1) (a0,a1,⋯,an−1),用 n ( n ≥ 0 ) n(n\\geq0) n(n≥0) 表示线性表的长度(即线性表中元素的个数)。当 n = 0 n=0 n=0 时,表示线性表是一个空表,不包含任何数据元素。
线性表的逻辑特征:每个元素最多只有一个前驱元素,也最多只有一个后继元素。
二、线性表的抽象数据类型描述
数 据 对 象 : D = a i ∣ 0 ≤ i ≤ n − 1 , n ≥ 0 , a i 为 E 类 型 数 据 关 系 : r = < a i , a i + 1 > ∣ a i , a i + 1 ∈ D , i = 0 , ⋯ , n − 2 基 本 运 算 : fromlist(a) : 根 据 数 组 a 的 全 部 元 素 建 立 线 性 表 add(e) : 将 元 素 e 添 加 到 线 性 表 的 末 尾 insert(i,e) : 插 入 元 素 e 作 为 序 号 i 的 元 素 delete(i) : 删 除 序 号 为 i 的 元 素 getelem(i) : 获 取 序 号 为 i 的 元 素 setelem(i,e) : 设 置 序 号 i 的 元 素 值 为 e getno(e) : 求 线 性 表 中 第 一 个 值 为 e 的 元 素 的 序 号 getsize() : 获 取 线 性 表 的 长 度 display() : 输 出 线 性 表 的 所 有 元 素 \\beginaligned &数据对象:D=\\a_i|0\\leq i\\leq n-1,n\\geq0,a_i为E类型\\ \\\\ &数据关系:r=\\<a_i,a_i+1>|a_i,a_i+1\\in D,i=0,\\cdots,n-2\\ \\\\ &基本运算:\\\\ &\\quad \\textfromlist(a):根据数组a的全部元素建立线性表 \\\\ &\\quad \\textadd(e):将元素e添加到线性表的末尾 \\\\ &\\quad \\textinsert(i,e):插入元素e作为序号i的元素 \\\\ &\\quad \\textdelete(i):删除序号为i的元素 \\\\ &\\quad \\textgetelem(i):获取序号为i的元素 \\\\ &\\quad \\textsetelem(i,e):设置序号i的元素值为e \\\\ &\\quad \\textgetno(e):求线性表中第一个值为e的元素的序号 \\\\ &\\quad \\textgetsize():获取线性表的长度 \\\\ &\\quad \\textdisplay():输出线性表的所有元素 \\\\ \\endaligned 数据对象:D=ai∣0≤i≤n−1,n≥0,ai为E类型数据关系:r=<ai,ai+1>∣ai,ai+1∈D,i=0,⋯,n−2基本运算:fromlist(a):根据数组a的全部元素建立线性表add(e):将元素e添加到线性表的末尾insert(i,e):插入元素e作为序号i的元素delete(i):删除序号为i的元素getelem(i):获取序号为i的元素setelem(i,e):设置序号i的元素值为egetno(e):求线性表中第一个值为e的元素的序号getsize():获取线性表的长度display():输出线性表的所有元素
三、顺序表的基本概念
线性表有两种存储结构:顺序存储和链式存储,本文将主要讲解顺序存储。
线性表的顺序存储是把线性表中的所有元素按照其逻辑顺序依次存储到存储器中一块连续的存储空间。线性表的顺序存储结构称为顺序表。
接下来我们将采用Python中的列表来实现顺序表。顺序表通常会有一个最大容量 capacity
,当要存储的元素个数大于 capacity
时,我们可以对顺序表进行扩容(例如将 capacity
扩大两倍)。
class SqList:
def __init__(self, capacity):
self.capacity = capacity # 最大容量
self.data = [None] * self.capacity # 用于存储数据
self.size = 0 # 顺序表的元素个数
我们可以创建一个 resize
函数用来修改线性表的最大容量:
def resize(self, newcapacity):
assert newcapacity >= 0
if newcapacity >= self.capacity:
self.data = self.data + [None] * (newcapacity - self.capacity)
else:
self.data = self.data[:newcapacity]
self.capacity = newcapacity
四、顺序表的实现
4.1 从数组中建立顺序表
给定列表 a
,我们需要通过该列表来建立相对应的顺序表。
def fromlist(self, a):
for i in range(len(a)):
# 出现上溢出时将容量扩大2倍
if self.size == self.capacity:
self.resize(self.size * 2)
# 因为self.size是从0开始递增的
self.data[self.size] = a[i]
self.size += 1
时间复杂度为 O ( n ) \\mathcalO(n) O(n),其中 n n n 表示顺序表中的元素个数。
4.2 将元素添加到顺序表末尾
def add(self, e):
# 防止溢出
if self.size == self.capacity:
self.resize(self.size * 2)
self.data[self.size] = e
self.size += 1
4.3 插入元素
要在位置
i
i
i 处插入元素
e
e
e,我们需要将 self.data[i, i+1, ..., n-1]
的每个元素均后移一位。
def insert(self, i, e):
assert 0 <= i <= self.size
if self.size == self.capacity:
self.resize(self.size * 2)
for j in range(self.size, i, -1):
self.data[j] = self.data[j - 1]
self.data[i] = e
self.size += 1
平均时间复杂度: O ( n ) \\mathcalO(n) O(n)。
4.4 删除元素
要删除位置
i
i
i 处的元素,我们需要将 self.data[i+1, ..., n-1]
的每个元素均前移一位。
def delete(self, i):
assert 0 <= i < self.size
for j in range(i, self.size - 1):
self.data[j] = self.data[j + 1]
self.size -= 1
# 自适应缩小容量以节省空间
if self.size < self.capacity / 2:
self.resize(self.capacity / 2)
平均时间复杂度: O ( n ) \\mathcalO(n) O(n)。
4.5 获取元素
def __getitem__(self, i):
assert 0 <= i < self.size
return self.data[i]
4.6 设置元素
def __setitem__(self, i, x):
assert 0 <= i < self.size
self.data[i] = x
4.7 查找第一个为e的序号
def getno(self, e):
for i in range(self.size):
if self.data[i] == e:
return i
# 未找到返回-1
return -1
4.8 获取顺序表长度
def getsize(self):
return self.size
4.9 打印顺序表
def display(self):
print(*self.data[:self.size])
五、验证我们的顺序表
sqlist = SqList(10)
sqlist.fromlist(list(range(10)))
sqlist.display()
# 0 1 2 3 4 5 6 7 8 9
sqlist.add(33)
sqlist.insert(3, 19)
sqlist.delete(0)
sqlist.display()
# 1 2 19 3 4 5 6 7 8 9 33
sqlist[10] = 3
print(sqlist[1])
# 2
print(sqlist.getno(3))
# 3
print(sqlist.getsize())
# 11
sqlist.display()
# 1 2 19 3 4 5 6 7 8 9 3
六、顺序表的一些应用
6.1 翻转顺序表
即若原始顺序表为 ( 4 , 3 , 2 , 1 ) (4,3,2,1) (4,3,2,1),翻转后的顺序表应为 ( 1 , 2 , 3 , 4 ) (1,2,3,4) (1,2,3,4)。
def reverse(sqlist):
i, j = 0, sqlist.getsize() - 1
while i < j:
sqlist[i], sqlist[j] = sqlist[j], sqlist[i]
i += 1
j -= 1
sqlist = SqList(5)
sqlist.fromlist(list(range(5)))
sqlist.display()
# 0 1 2 3 4
reverse(sqlist)
sqlist.display()
# 4 3 2 1 0
时间复杂度 O ( n ) \\mathcalO(n) O(n),空间复杂度 O ( 1 ) \\mathcalO(1) O(1)。
6.2 删除k个元素
设计一个算法从位置
i
i
i 开始删除其后的
k
k
k 个元素(包括
i
i
i)。例如设
L
=
(
1
,
2
,
3
,
4
,
5
)
,
以上是关于数据结构Python版——顺序表的主要内容,如果未能解决你的问题,请参考以下文章