【数据结构与算法】:手搓顺序表(Python篇)

文章目录

      • 一、顺序表的概念
      • 二、顺序表的实现
        • 1. 顺序表的创建
          • 1.1 扩容
          • 1.2 整体建立顺序表
        • 2. 顺序表的基本运算算法
          • 2.1 顺序表的添加(尾插)
          • 2.2 指定位置插入
          • 2.3 指定位置删除
          • 2.4 顺序表的查找
          • 2.5 顺序表元素的索引访问
          • 2.6 顺序表元素的修改
          • 2.7 顺序表长度
          • 2.8 顺序表的输出
      • 三、完整代码
      • 四、代码验证

一、顺序表的概念

顺序表是一种线性的数据结构,其中数据元素按照特定的顺序依次存储在连续的内存空间中。它由一系列元素组成,每个元素都与唯一的索引(或者叫下标)相关联,索引从 0 开始递增。
顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储。在数组上完成数据的增删查改。
下面这张图中,最下面那行数字0~9代表的是元素的索引,天蓝色的柱子中的数字代表的是顺序表中的元素,顺序表中的元素必须是同一数据类型的,数据类型可以是整数、浮点数、字符串等等。
在这里插入图片描述

二、顺序表的实现

设计顺序表类为SqList,主要包含存放元素的data列表和表示实际元素个数的size属性。因为Python属于弱类型语言,没必要专门设计像C++或则Java中的泛型类,在应用SqList时可以指定其元素为任意合法数据类型。

创建顺序表类

# 顺序表类
class SqList:# 初始化def __init__(self):self.initcapacity = 5  # 初始容量设置为5self.capacity = self.initcapacity  # 容量设置为初始容量self.data = [None] * self.capacity  # 设置顺序表的空间self.size = 0  # 长度设为0
1. 顺序表的创建
1.1 扩容

顺序表在实现各种基本运算如插入和删除时会涉及到容量的更新,所以要设计一个方法将data列表的容量改变为newcapacity。

# 扩容
def resize(self, newcapacity):  # 改变顺序表的容量为newcapacityassert newcapacity >= 0oldata = self.dataself.data = [None] * newcapacityself.capacity = newcapacityfor i in range(self.size):self.data[i] = oldata[i]

这里就是先让olddata指向data,为data重新分配一个容量为newcapacity的空间,再将olddata中的所有元素复制到data中,复制中所有的元素的序号和长度size不变。原data空间会被系统自动释放掉。

1.2 整体建立顺序表

该方法就是从空顺序表开始,由含若干个元素的列表a的全部元素整体创建顺序表,即依次将a中的元素添加到data列表的末尾,当出现上溢出时按实际元素个数size的两倍扩大容量。

# 整体创建顺序表
def CreateList(self, a):  # 有数组a中的元素整体建立顺序表for i in range(0, len(a)):if self.size == self.capacity:  # 出现上溢出时self.resize(2 * self.size)  # 扩容self.data[self.size] = a[i]self.size += 1  # 添加后元素增加1

时间复杂度为O(n), n表示顺序表中的元素个数。

2. 顺序表的基本运算算法
2.1 顺序表的添加(尾插)

将元素e添加到顺序表的末尾:Add(e)
在data列表的尾部插入元素e,在插入中出现上溢出时按实际元素个数size的两倍扩大容量。

# 顺序表的添加(尾插)
def Add(self, e):  # 在线性表的末尾添加一个元素if self.size == self.capacity:self.resize(2 * self.size)  # 顺序表空间满时倍增容量self.data[self.size] = e  # 添加元素eself.size += 1  # 长度加1

该算法中调用一次resize()方法的时间复杂度为O(n),但n次Add操作仅需要扩大一次data空间,所以平均时间复杂度仍然为O(1)。

2.2 指定位置插入

在顺序表中插入e作为第i个元素:Insert(i,e)
在顺序表中序号i的位置上插入一个新元素e。若参数i合法(0<= i <= n),先将data[i…n-1]的每个元素均后移一个位置(从data[n - 1]元素开始移动),腾出一个空位置data[i]插入新元素e,最后将长度size增1。在插入元素时若出现上溢出,则按两倍size扩大容量。
在这里插入图片描述

# 指定位置插入
def Insert(self, i, e):  # 在线性表中序号为i的位置插入元素assert 0 <= i <= self.sizeif self.size == self.capacity:  # 满时扩容self.resize(2 * self.size)for j in range(self.size, i - 1, -1):  # 疆data[i]及后面的元素后移一位self.data[j] = self.data[j - 1]self.data[i] = e  # 插入元素eself.size += 1  # 长度加1

该算法的时间主要花在元素的移动上,元素移动的次数不仅与表长n有关,而且与插入位置i有关。有效插入位置i的取值是0~n,共有n + 1个位置可以插入元素:

  1. 当i = 0时,移动次数为n,达到最大值。
  2. 当i = n时,移动次数为0,达到最小值。
  3. 其他情况,需要移动data[i…n - 1]的元素,移动次数为(n - 1)- i + 1 = n - i。

时间复杂度为O(n)。

2.3 指定位置删除

顺序表中删除第i个数据元素:Delete(i)
该算法删除顺序表中序号i的元素。若参数i合法(0<= i < n),删除操作是将data[i + 1 … n - 1]的元素均向前移动一个位置(从data[i + 1]元素开始移动),这样覆盖了元素data[i],从而达到删除该元素的目的,最后将顺序表的长度减一。若当前容量大于初始容量并且实际长度仅为当前容量的1/4(缩容条件),则将当前容量减半。
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

def Delete(self, i):  # 在线性表中删除序号为i的元素assert 0 <= i <= self.size - 1for j in range(i, self.size - 1):self.data[j] = self.data[j + 1]  # 将data[j]之后的元素前移一位self.size -= 1  # 长度减一if self.capacity > self.initcapacity and self.size <= self.capacity / 4:self.resize(self.capacity // 2)  # 满足要求容量减半

该算法的时间主要花在元素的移动上,元素移动的次数不仅与表长n有关,而且与删除位置i有关。有效删除位置i的取值是0~n - 1,共有n个位置可以插入元素:

  1. 当i = 0时,移动次数为n - 1,达到最大值。
  2. 当i = n - 1时,移动次数为0,达到最小值。
  3. 其他情况,需要移动data[i +1 … n - 1]的元素,移动次数为(n - 1)- (i + 1)+ 1 = n - i - 1。

时间复杂度为O(n)。

2.4 顺序表的查找

求顺序表中第一个值为e的元素的序号:GetNo(e)
在data列表中从前向后顺序查找第一个值与e相等的元素的序号,若不存在这样的元素,则返回-1。
在这里插入图片描述

def GetNo(self, e):  # 查找第一个为e的元素的下标i = 0while i < self.size and self.data[i] != e:  # 查找元素ei += 1if i >= self.size:return -1else:return i

该算法的时间复杂度为O(n),其中n表示顺序表中的元素个数。

2.5 顺序表元素的索引访问

求顺序表中序号i的元素值:GetElem(i)
当序号i合法时(0<= i < size)返回data[i]。
在这里插入图片描述

def __getitem__(self, i):  # 求序号为i的元素assert 0 <= i < self.sizereturn self.data[i]

对于顺序表对象L,可以通过L[i]调用上述运算获取序号i的元素值。时间复杂度为O(1)。

2.6 顺序表元素的修改

设置顺序表中序号i的元素值:SetElem(i,e)
在这里插入图片描述

def __setitem__(self, i, value):  # 设置序号为i的元素assert 0 <= i < self.sizeself.data[i] = value

对于顺序表对象L,可以通过L[i] = e调用上述运算将序号i的元素值设置为e。该算法的时间复杂度为O(1)

2.7 顺序表长度

求顺序表的长度:getsize()
返回顺序表的长度(实际元素个数size)。

def getsize(self):  # 返回长度return self.size

时间复杂度为O(1)

2.8 顺序表的输出

输出顺序表的所有元素:display()
依次输出顺序表中的所有元素值。

def display(self):  # 输出顺序表for i in range(0, self.size):print(self.data[i], end=' ')print()  # 换行

时间复杂度为O(n),n表示顺序表中的元素个数。

三、完整代码

# 顺序表类
class SqList:# 初始化def __init__(self):self.initcapacity = 5  # 初始容量设置为5self.capacity = self.initcapacity  # 容量设置为初始容量self.data = [None] * self.capacity  # 设置顺序表的空间self.size = 0  # 长度设为0# 扩容def resize(self, newcapacity):  # 改变顺序表的容量为newcapacityassert newcapacity >= 0oldata = self.dataself.data = [None] * newcapacityself.capacity = newcapacityfor i in range(self.size):self.data[i] = oldata[i]# 整体创建顺序表def CreateList(self, a):  # 有数组a中的元素整体建立顺序表for i in range(0, len(a)):if self.size == self.capacity:  # 出现上溢出时self.resize(2 * self.size)  # 扩容self.data[self.size] = a[i]self.size += 1  # 添加后元素增加1def Add(self, e):  # 在线性表的末尾添加一个元素if self.size == self.capacity:self.resize(2 * self.size)  # 顺序表空间满时倍增容量self.data[self.size] = e  # 添加元素eself.size += 1  # 长度加1def getsize(self):  # 返回长度return self.sizedef __getitem__(self, i):  # 求序号为i的元素assert 0 <= i < self.sizereturn self.data[i]def __setitem__(self, i, value):  # 设置序号为i的元素assert 0 <= i < self.sizeself.data[i] = valuedef GetNo(self, e):  # 查找第一个为e的元素的下标i = 0while i < self.size and self.data[i] != e:  # 查找元素ei += 1if i >= self.size:return -1else:return i# 指定位置插入def Insert(self, i, e):  # 在线性表中序号为i的位置插入元素assert 0 <= i <= self.sizeif self.size == self.capacity:  # 满时扩容self.resize(2 * self.size)for j in range(self.size, i - 1, -1):  # 疆data[i]及后面的元素后移一位self.data[j] = self.data[j - 1]self.data[i] = e  # 插入元素eself.size += 1  # 长度加1def Delete(self, i):  # 在线性表中删除序号为i的元素assert 0 <= i <= self.size - 1for j in range(i, self.size - 1):self.data[j] = self.data[j + 1]  # 将data[j]之后的元素前移一位self.size -= 1  # 长度减一if self.capacity > self.initcapacity and self.size <= self.capacity / 4:self.resize(self.capacity // 2)  # 满足要求容量减半def display(self):  # 输出顺序表for i in range(0, self.size):print(self.data[i], end=' ')print()  # 换行

四、代码验证

if __name__ == '__main__':L = SqList()  # 实例化print('建立空顺序表L, 其容量为 %d' % (L.capacity))a = [1, 2, 3, 4, 5]print('1~6创建L')L.CreateList(a)print('L[容量 = %d, 长度 = %d]:' % (L.capacity, L.getsize()), end=' '), L.display()print('插入6~10')for i in range(6, 11):L.Add(i)print('L[容量 = %d, 长度 = %d]:' % (L.capacity, L.getsize()), end=' '), L.display()print('序号为2的元素 = %d' % (L[2]))print('设置序号为2的元素为20')L[2] = 20print('L[容量 = %d, 长度 = %d]:' % (L.capacity, L.getsize()), end=' '), L.display()x = 6print('第一个值为%d的元素序号 = %d' % (x, L.GetNo(x)))n = L.getsize()for i in range(n - 2):print('删除首元素')L.Delete(0)print('L[容量 = %d, 长度 = %d]:' % (L.capacity, L.getsize()), end=' '), L.display()

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/4162.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

《Kafka 3.x.x 入门到精通》

Kafka 3.x.x 入门到精通 Kafka是一个由Scala和Java语言开发的&#xff0c;经典高吞吐量的分布式消息发布和订阅系统&#xff0c;也是大数据技术领域中用作数据交换的核心组件之一。以高吞吐&#xff0c;低延迟&#xff0c;高伸缩&#xff0c;高可靠性&#xff0c;高并发&#x…

两大成果发布!“大规模量子云算力集群”和高性能芯片展示中国科技潜力

在当前的科技领域&#xff0c;量子计算的进步正日益引起全球的关注。中国在这一领域的进展尤为显著&#xff0c;今天&#xff0c;北京量子信息科学研究院&#xff08;以下简称北京量子院&#xff09;和中国科学院量子信息与量子科技创新研究院&#xff08;以下简称量子创新院&a…

微信小程序:8.WXSS

WXSS和CSS的关系 WXSS具有CSS大部分特性&#xff0c;同时&#xff0c;WXSS还对CSS进行扩充以及修改&#xff0c;适应微信小程序的开发。 与CSS相比&#xff0c;WXSS扩展的特性有&#xff1a; rpx尺寸单位imprt样式导入 rpx尺寸单位 rpx是微信小程序中独有的&#xff0c;用来…

Vue 使用Canvas画布手写电子版签名 保存 上传服务端

电子版签名效果 定义画布 <canvas width"500"height"250"ref"cn"mousedown"cnMouseDown"mousemove"cnMouseMove"mouseup"cnMouseUp"style"width:500px;height: 250px;background-color:snow;padding: 10p…

在Docker中部署Java应用:Java版本隔离的实践案例

在Docker中部署Java应用&#xff1a;Java版本隔离的实践案例 人生就是一场又一场的相遇&#xff0c;一个明媚&#xff0c;一个忧伤&#xff0c;一个华丽&#xff0c;一个冒险&#xff0c;一个倔强&#xff0c;一个柔软&#xff0c;最后那个正在成长。 背景需求 在软件开发和部…

Python实践应用|NC文件读取

import netCDF4 as nc import numpy as np import matplotlib.pyplot as plt# 打开NC文件 nc_file E:/NC_file/air.sig995.2012.nc # 将your_file.nc替换为你的NC文件路径 nc_data nc.Dataset(nc_file, r)# 查看NC文件中包含的变量 print("Variables in the NC file:&q…

【数据结构】Map和Set(1)

&#x1f9e7;&#x1f9e7;&#x1f9e7;&#x1f9e7;&#x1f9e7;个人主页&#x1f388;&#x1f388;&#x1f388;&#x1f388;&#x1f388; &#x1f9e7;&#x1f9e7;&#x1f9e7;&#x1f9e7;&#x1f9e7;数据结构专栏&#x1f388;&#x1f388;&#x1f388;&…

【jQuery】看一眼就会用的jquery库之续章!

jQuery&#xff08;js框架&#xff09; 17、操作节点 创建节点&#xff1a; 创建节点只需要将元素放在jQuery的工厂函数中//创建一个button按钮let $btn$("<input typebutton>");//创建一个列表项let $li$("<li>选项</li>");添加节点…

医保购药小程序开发指南:利用智慧药房系统源码实现智能服务

医保购药小程序为患者提供了便捷的药品购买渠道&#xff0c;同时也为药店和医疗机构提供了智能化管理和服务的平台。接下来&#xff0c;小编将介绍如何利用智慧药房系统源码实现医保购药小程序的开发&#xff0c;并探讨如何实现智能化的服务。 第一部分&#xff1a;智慧药房系统…

如何使用IDEA直接连接MySQL数据库

如何使用IDEA直接连接MySQL数据库 新建一个空项目打开DataBase窗口连接数据库第一次连接 需要先下载驱动上一步驱动下载太慢怎么办&#xff1f;下载好驱动后 测试连接 新建一个空项目 打开DataBase窗口 连接数据库 第一次连接 需要先下载驱动 如果这里下载的很慢 看下一步解决…

SpringBoot笔记1

继承父工程 <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.7.10</version></parent>java 无效的源发行版 17 解决方法 <build><plugins>…

python基础知识—while和for循环(三)

&#x1f3ac; 秋野酱&#xff1a;《个人主页》 &#x1f525; 个人专栏:《Java专栏》《Python专栏》 ⛺️心若有所向往,何惧道阻且长 文章目录 一&#xff1a;while循环1.1程序的三种执行流程1.2while循环1.3循环变量和死循环 二&#xff1a;for循环2.1for循环2.2range 一&…

安装crossover游戏提示容量不足怎么办 如何把游戏放到外置硬盘里 Mac电脑清理磁盘空间不足

CrossOver作为一款允许用户在非原生操作系统上运行游戏和应用程序的软件&#xff0c;为不同平台的用户提供了极大的便利。然而&#xff0c;随着游戏文件大小的不断增加&#xff0c;内置硬盘的容量往往无法满足安装需求。幸运的是&#xff0c;通过一些简单的步骤&#xff0c;我们…

Penpad 再获 Animoca Brands 投资,全新生态历程

Penpad 是 Scroll 生态的 LaunchPad & Yield Aggregator 平台&#xff0c;该平台近日在融资上取得了系列进展。据悉&#xff0c;Penpad 在前不久率先获得了来自于 Gate Labs 以及 Scroll 联合创始人 Sandy Peng 的融资&#xff0c;并且在近日&#xff0c;其又获得了来自于知…

Amazon云计算AWS之[4]非关系型数据库服务SimpleDB和DynamoDB

文章目录 简介非关系型VS关系数据库SimpleDB域条目属性值SimpleDB的使用 DynamoDBSimpleDB VS DynamoDB 简介 非关系型数据库服务主要用于存储结构化的数据&#xff0c;并为这些数据提供查找、删除等基本的数据库功能。AWS中提供的非关系型数据库主要包括SimpleDB和DynamoDB …

(学习日记)2024.04.20:UCOSIII第四十八节:各文件功能概览

写在前面&#xff1a; 由于时间的不足与学习的碎片化&#xff0c;写博客变得有些奢侈。 但是对于记录学习&#xff08;忘了以后能快速复习&#xff09;的渴望一天天变得强烈。 既然如此 不如以天为单位&#xff0c;以时间为顺序&#xff0c;仅仅将博客当做一个知识学习的目录&a…

牛客网:S老师的公式 ← 取模运算

【题目来源】https://ac.nowcoder.com/acm/contest/76652/A【题目描述】 S 老师丢给你了一个简单的数学问题&#xff1a; 求 。 请你求出答案。【输入格式】 一行一个整数 n (1≤n≤10^6)。【输出格式】 一行一个整数表示答案。【说明】 例如&#xff0c;若n3&#xff0c;则本题…

【redis】Redis数据类型(一)——String类型(包含redis通用命令)

目录 Redis通用命令String类型常用的操作命令一些特殊命令详解setnx示例使用 setrange示例 mset示例 msetnx示例 append示例 getset示例 incr示例使用1.计数器2.限速器 bitcount示例使用&#xff1a;使用 bitmap 实现用户上线次数统计性能 String类型String类型简介String类型的…

统一威胁情报如何赋能SOC应对复杂威胁?

安全运营中心&#xff08;SOC&#xff09;是组织网络安全战略的核心组成部分&#xff0c;扮演着至关重要的角色。其负责实时监控整个IT基础设施&#xff0c;以检测、响应和预防各类网络安全威胁。网络安全威胁日益复杂且多变的数字化时代&#xff0c;攻击平面泛化、基础设施复杂…

C#技巧之窗体去鼠标化

简介 在窗体程序中不用鼠标&#xff0c;直接使用键盘完成想要的操作。 实现的方法有两种&#xff0c;一种是使用键盘上的Tab键使控件获得焦点&#xff0c;然后用enter键触发该控件上的事件&#xff08;一般为click事件&#xff09;。另一种是&#xff0c;为控件添加快捷键&am…