返回顶部
首页 > 资讯 > 后端开发 > Python >如何分析Python数据结构与算法中的顺序表
  • 500
分享到

如何分析Python数据结构与算法中的顺序表

2023-06-26 03:06:17 500人浏览 八月长安

Python 官方文档:入门教程 => 点击学习

摘要

这篇文章的内容主要围绕如何分析python数据结构与算法中的顺序表进行讲述,文章内容清晰易懂,条理清晰,非常适合新手学习,值得大家去阅读。感兴趣的朋友可以跟随小编一起阅读吧。希望大家通过这篇文章有所收获!0. 学习目标线性表在计算机中的表示

这篇文章的内容主要围绕如何分析python数据结构与算法中的顺序表进行讲述,文章内容清晰易懂,条理清晰,非常适合新手学习,值得大家去阅读。感兴趣的朋友可以跟随小编一起阅读吧。希望大家通过这篇文章有所收获!


0. 学习目标

线性表在计算机中的表示可以采用多种方法,采用不同存储方法的线性表也有着不同的名称和特点。线性表有两种基本的存储结构:顺序存储结构和链式存储结构。本节将介绍顺序存储结构的特点以及各种基本运算的实现。
通过本节学习,应掌握以下内容:

线性表的顺序存储及实现方法

顺序表基本操作的实现

利用顺序表的基本操作实现复杂算法

1. 线性表的顺序存储结构

1.1 顺序表基本概念

线性表的顺序存储是把线性表的数据元素按逻辑次序依次存放在一组连续的存储单元中,即逻辑结构上相邻的两个数据元素存储在计算机内的物理存储位置也是相邻的,这种存储方法为整个线性表分配一整个内存块保存线性表的元素,借助数据元素在计算机内的物理位置表示线性表中数据元素之间的逻辑关系。采用顺序存储结构表示的线性表简称顺序表 (Sequential List)。

顺序表具有以下两个基本特点:

顺序表的所有元素所占的存储空间是连续的;

顺序表中各数据元素在存储空间中是按逻辑顺序依次存放的。

由于线性表的所有数据元素属于同一数据类型,所以每个元素占用的空间(字节数)相同。因此,要在此结构中查找某一个元素是很方便的,即只要知道顺序表首地址和每个数据元素在内存所占字节的大小,就可求出第 i ii 个数据元素的地址。通过使用特定元素的序号,可以在常数时间内访问数据元素,因此可以说顺序表具有按数据元素的序号随机存取的特点。

假设线性表中的第一个数据元素的存储地址(即顺序表第一个字节的地址,也称首地址)为id(a1),每一个数据元素占k个字节,则线性表中第i个元素ai在计算机中的存储地址为:

id(ai)=id(a1)+(i−1)×k (1≤i≤n)

从上式可以看出,访问顺序表数据元素的过程只需要一次乘法和一次加法。由于这两个操作只需要常数时间,因此可以说顺序表访问可以在常数时间内进行。

也就是说,顺序表中的每一个数据元素在计算机存储空间中的存储地址由该元素在线性表中的序号惟一确定。假设有一长度为n的线性表 (a1,a2,...,an),那么其在计算机中的顺序存储结构可以用下图表示:

如何分析Python数据结构与算法中的顺序表

1.2 顺序表的优缺点

顺序表的优点:

  • 简单易用

  • 可以快速访问元素

顺序表的缺点:

  • 固定大小:顺序表的大小是静态的(使用前需要指定顺序表大小)

  • 基于位置插入元素较复杂:要在给定位置插入元素,可能需要移动现有元素来创建一个空位置,以便在所需位置插入新元素;如果要在开头添加元素,那么移位操作的开销就更大了

为了解决顺序表具有固定大小的缺陷,动态顺序表的概念被提出。

1.3 动态顺序表

动态顺序表(也称为可增长顺序表、可调整大小的顺序表、动态表)是一种随机访问、大小可变的顺序表数据结构,允许添加或删除元素,Python 内置的 list 就是一种动态顺序表。

实现动态顺序表的一种简单方法是从一些固定大小的顺序表开始。一旦该顺序表变满,就创建高于原始顺序表大小的新顺序表;同样,如果顺序表中的元素过少,则将缩小顺序表大小。

接下来,为了更好的理解顺序表,我们将使用 Python 实现顺序表。

2. 顺序表的实现

在具体实现时,使用 Python 中的列表来对应连续的存储空间。设最多可存储 max_size 个元素,为保存线性表的长度需定义一个整型变量 num_items。由于,Python 列表中索引从 0 开始,因此,线性表的第i(1≤i≤n)个元素存放在列表索引为i−1的列表元素中,为保持一致性,我们实现的顺序表的序号同样从 0 开始(也可以根据需要索引从 1 开始,只需要进行简单修改)。

如何分析Python数据结构与算法中的顺序表

2.1 顺序表的初始化

顺序表的初始化需要三部分信息:items 列表用于存储数据元素,max_size 用于存储 items 列表的最大长度,以及 num_items 用于记录 items 列表的当前使用的位置,即顺序表中的数据元素数量。

class SequentialList:    def __init__(self, max_size=10):        self.items = [None] * max_size        self.num_items = 0        self.max_size = max_size

初始化代码通过创建一个包含 10 个 None 值的列表来构建一个 SequentialList 对象,内部 items 列表的初始大小 max_size 默认为 10,也可以传递更大的顺序表大小作为初始大小,该列表也可以在需要时会动态增长。创建 SequentialList 对象的时间复杂度为O(1)。

如下图所示,是一个包含 5 个数据元素的 SequentialList 对象:

如何分析Python数据结构与算法中的顺序表

2.2 获取顺序表长度

这里所说的顺序表长度,指顺序表中数据元素的个数,由于我们在顺序表中使用 num_items 跟踪顺序表中的项数,求取顺序表长度只需要重载 __len__ 从对象返回 num_items 的值,因此时间复杂度为O(1):

    def __len__(self):        return self.num_items

如果在 SequentialList 对象中没有跟踪列表的项数,那么计算顺序表长度的时间复杂度为O(n)。

2.3 读取指定位置元素

为了实现读取顺序表指定位置元素的操作,我们将重载 __getitem__ 操作,操作的复杂度为O(1)。同时,我们希望确保索引在可接受的索引范围内,否则将像内置列表类一样引发 IndexError 异常:

    def __getitem__(self, index):        if index >= 0 and index < self.num_items:            return self.items[index]        raise IndexError('SequentialList index out of range')

我们也可以实现修改指定位置元素的操作,只需要重载 __setitem__ 操作,其复杂度同样为O(1):

    def __setitem__(self, index, val):        if index >= 0 and index < self.num_items:            self.items[index] = val            return        raise IndexError("SequentialList assignment index out of range")

2.4 查找指定元素

要确定值为 x 的元素在顺序表中的位置,需要依次比较各元素。当查询到第一个满足条件的数据元素时,返回其下标,否则像内置列表类一样引发 ValueError 异常,表示查找失败。

    def locate(self, item):        for i in range(self.num_items):            if self.items[i] == item:                return i        raise ValueError("{} is not in sequential list".fORMat(item))

在查找过程中,数据元素比较次数的平均值为(n+1)/2,因此时间复杂度为O(n)。

2.5 在指定位置插入新元素

实现在指定位置插入新元素之前,我们首先看下如何在顺序表末尾追加元素。追加时,如果有空闲空间,只需要在 self.items 列表的末尾再添加一项,而当 self.items 列表填满时,我们必须增加 self.items 列表的大小,为需要追加的新元素创建空间,创建的新 self.items 大小与 self.items 的当前长度成正比。

为了使追加操作在O(1)时间内运行,我们不能在每次需要更多空间时仅增加一个空闲位置,事实证明,每次增加 25% 的空间就足以保证O(1)复杂度。选择增加空间的百分比并不重要,每次增加 10% 或100%的空间,同样可以使时间复杂度为O(1)。这里选择 25% 的原因是可以在不占用太多计算机内存的情况下多次使用追加操作扩展列表。

    def __alloc(self):        new_size = (self.max_size // 4) + self.max_size + 1        new_items = [None] * new_size        for i in range(self.num_items):            new_items[i] = self.items[i]                self.items = new_items        self.max_size = new_size    def append(self, item):        if self.num_items == self.max_size:            self.__alloc()                self.items[self.num_items] = item        self.num_items += 1

要插入新数据元素到顺序表中,必须为新元素腾出空间,下图表示顺序表中的列表在进行插入操作前后,其数据元素在列表中下标的变化情况:

如何分析Python数据结构与算法中的顺序表

完成如上的插入操作要经过如下步骤:

线性表中指定位置及其之后的元素,依次向后移动一个位置,空出索引为i的位置

数据元素 x 插入到第i个存储位置

插入结束后使线性表的长度增加 1

需要注意的是,如果线性表空间已满,首先需要分配新的空间。如果提供的索引大于列表的大小,则将新项 x 附加到列表的末尾。插入时间元素操作的时间复杂度为O(n)。

    def insert(self, index, item):        if self.num_items == self.max_size:            self.__alloc()        if index < self.num_items and index >= 0:            for j in range(self.num_items-1, index-1, -1):                self.items[j+1] = self.items[j]            self.items[index] = item            self.num_items += 1        elif index >= self.num_items:            self.append(item)        else:            raise IndexError("SequentialList assignment index out of range")

2.6 删除指定位置元素

当删除列表中特定索引处的数据元素时,我们必须将其之后的所有元素向下移动以保证内部列表中没有无效数据。下图表示一个顺序表在进行删除运算前后,其数据元素下标的变化:

如何分析Python数据结构与算法中的顺序表

在线性表上完成上述操作需要以下步骤:

在线性表中删除下标为i的元素,从索引为i+1到n&minus;1的元素依次向前移动依次向前移动一个位置,将所删除的索引为i的数据元素ai+1覆盖掉,从而保证逻辑上相邻的元素物理位置也相邻

修改顺序表长度,使其减 1

为了实现删除顺序表指定位置元素的操作,我们将重载 __getitem__ 操作,在顺序表上删除数据元素时大约需要移动表中一半的元素,显然该算法的时间复杂度为O(n)。

    def __delitem__(self, index):        for i in range(index, self.num_items-1):            self.items[i] = self.items[i+1]        self.num_items -= 1

2.7 其它一些有用的操作

为了更好的使用顺序表,接下来将介绍其它一些很有用的操作。
例如,将顺序表转换为字符串以便进行打印,使用 str 函数调用对象上的 __str__ 方法可以创建适合打印的字符串表示,__str__ 的返回结果的可读性很强:

    def __str__(self):        s = '['        for i in range(self.num_items):            s += repr(self.items[i])            if i < self.num_items - 1:                s += ', '        s += ']'        return s

我们也可以重载成员资格函数 __contain__ 来检查一个数据元素是否是顺序表中的元素之一。这样做的唯一方法是按顺序检查顺序表中的每个数据元素。如果找到该项目,则返回 True,否则返回 False 这种搜索方法称为线性搜索,之所以这样命名是因为它具有O(n)的时间复杂度:

    def __contains__(self, item):        for i in range(self.num_items):            if self.items[i] == item:                return True        return False

检查两个顺序表的相等性首先需要两个顺序表的类型相同以及两个顺序表必须具有相同的长度。在满足这两个先决条件的情况下,如果两个表中的所有元素都相等,则我们可以说两个顺序表相等,相等测试的时间复杂度为O(n),我们重载 __eq__ 方法实现此操作:

    def __eq__(self, another):        if type(another) != type(self) or self.num_items != another.num_items:            return False        for i in range(self.num_items):            if self.items[i] != another.items[i]:                return False        return True

3. 顺序表应用

接下来,我们首先对上述实现的顺序表进行测试,以验证操作的有效性,然后利用实现的基本操作来实现更复杂的算法。

3.1 顺序表应用示例

首先初始化一个顺序表 sample_sqlist,并在其中追加若干元素:

sample_sqlist = SequentialList()sample_sqlist.append(11)sample_sqlist.append(22)sample_sqlist.append(33)

我们可以直接打印顺序表中的数据元素、顺序表长度等信息:

print('顺序表数据元素为:', sample_sqlist)print('顺序表长度:', len(sample_sqlist))print('顺序表中第0个数据元素:', sample_sqlist[0])# 修改数据元素sample_sqlist[1] = 2022print('顺序表数据元素为:', sample_sqlist)

以上代码输出如下:

顺序表数据元素为: [11, 22, 33]

顺序表长度: 3

顺序表中第0个数据元素: 11

顺序表数据元素为: [11, 2022, 33]

接下来,我们将演示在指定位置添加/删除元素、以及如何查找指定元素等:

print('在顺序表位置1处添加元素2021')sample_sqlist.insert(1, 2021)print('添加元素后,顺序表数据元素为:', sample_sqlist)print('删除顺序表位置2处元素')del(sample_sqlist[2])print('删除数据后,顺序表数据元素为:', sample_sqlist)print('元素11的索引为{}'.format(sample_sqlist.locate(11)))print('11在顺序表中?', 11 in sample_sqlist)print('22在顺序表中?', 22 in sample_sqlist)

以上代码输出如下:

在顺序表位置1处添加元素2021

添加元素后,顺序表数据元素为: [11, 2021, 2022, 33]

删除顺序表位置2处元素

删除数据后,顺序表数据元素为: [11, 2021, 33]

元素11的索引为0

11在顺序表中? True

22在顺序表中? False

3.2 利用顺序表基本操作实现复杂操作

[1] 利用顺序表的基本操作,合并两个顺序表:

def add_sqlist(sqlist1, sqlist2):    result = SequentialList(max_size=sqlist1.num_items+sqlist2.num_items)    for i in range(sqlist1.num_items):        result.append(sqlist1[i])    for i in range(sqlist2.num_items):        result.append(sqlist2[i])    return result# 算法测试sqlist1 = SequentialList()sqlist2 = SequentialList()for i in range(10):    sqlist1.append(i)    sqlist2.append(i*5)print('顺序表1:', sqlist1, '顺序表2:', sqlist2)# 合并顺序表result = add_sqlist(sqlist1, sqlist2)print('合并顺序表:', result)

可以看到合并两个顺序表的时间复杂度为O(n),程序输出结果如下:

顺序表1: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 顺序表2: [0, 5, 10, 15, 20, 25, 30, 35, 40, 45]

合并顺序表: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 5, 10, 15, 20, 25, 30, 35, 40, 45]

[2] 利用顺序表 sqlist1 和 sqlist2 中公共数据元素生成新顺序表:

def commelem(sqlist1, sqlist2):    result = SequentialList()    for i in range(sqlist1.num_items):        if sqlist1[i] in sqlist2 and sqlist1[i] not in result:            result.append(sqlist1[i])    return result# 算法测试sqlist1 = SequentialList()sqlist2 = SequentialList()for i in range(5):    sqlist1.append(i*2)    sqlist1.append(i)    sqlist2.append(i*3)print('顺序表1:', sqlist1, '顺序表2:', sqlist2)# 合并顺序表result = commelem(sqlist1, sqlist2)print('两顺序表中的公共元素:', result)

可以看到算法的时间复杂度为O(n2),程序输出结果如下:

合并顺序表: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 5, 10, 15, 20, 25, 30, 35, 40, 45]

顺序表1: [0, 0, 2, 1, 4, 2, 6, 3, 8, 4] 顺序表2: [0, 3, 6, 9, 12]

两顺序表中的公共元素: [0, 6, 3]

感谢你的阅读,相信你对“如何分析Python数据结构与算法中的顺序表”这一问题有一定的了解,快去动手实践吧,如果想了解更多相关知识点,可以关注编程网网站!小编会继续为大家带来更好的文章!

--结束END--

本文标题: 如何分析Python数据结构与算法中的顺序表

本文链接: https://lsjlt.com/news/306671.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • 如何分析Python数据结构与算法中的顺序表
    这篇文章的内容主要围绕如何分析Python数据结构与算法中的顺序表进行讲述,文章内容清晰易懂,条理清晰,非常适合新手学习,值得大家去阅读。感兴趣的朋友可以跟随小编一起阅读吧。希望大家通过这篇文章有所收获!0. 学习目标线性表在计算机中的表示...
    99+
    2023-06-26
  • 详解Python数据结构与算法中的顺序表
    目录0. 学习目标1. 线性表的顺序存储结构1.1 顺序表基本概念1.2 顺序表的优缺点1.3 动态顺序表2. 顺序表的实现2.1 顺序表的初始化2.2 获取顺序表长度2.3 读取指...
    99+
    2024-04-02
  • Python数据结构树与算法分析
    目录1.示例2.术语及定义3.实现3.1 列表之列表3.2节点与引用4.二叉树的应用4.1解析树4.2树的遍历5.利用二叉堆实现优先级队列6.二叉搜索树6.1搜索树的实现7.平衡二叉...
    99+
    2024-04-02
  • python数据结构算法分析
    目录1.算法分析的定义2.大O记法3.不同算法的大O记法3.1清点法3.2排序法3.3蛮力法3.4计数法4.列表和字典操作的复杂度4.1列表4.2字典前文学习: python数据类型...
    99+
    2024-04-02
  • Python数据结构与算法之算法分析详解
    目录0. 学习目标1. 算法的设计要求1.1 算法评价的标准1.2 算法选择的原则2. 算法效率分析2.1 大O表示法2.2 常见算法复杂度2.3 复杂度对比3. 算法的存储空间需求...
    99+
    2024-04-02
  • 分析Java数据结构与算法
    本篇内容主要讲解“分析Java数据结构与算法”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“分析Java数据结构与算法”吧!1.什么是二叉树二叉树:就是每个节点都...
    99+
    2024-04-02
  • C++如何实现数据结构的顺序表
    这篇文章给大家分享的是有关C++如何实现数据结构的顺序表的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。代码1.SeqList.h#ifndef SEQLIST_H#define SEQLIST...
    99+
    2023-06-25
  • Python高级数据结构与算法实例分析
    本文小编为大家详细介绍“Python高级数据结构与算法实例分析”,内容详细,步骤清晰,细节处理妥当,希望这篇“Python高级数据结构与算法实例分析”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。一、简介我们将从以...
    99+
    2023-07-05
  • python数据结构算法的示例分析
    小编给大家分享一下python数据结构算法的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!1.算法分析的定义有这样一个问题:当两个看上去不同的程序 解决同...
    99+
    2023-06-22
  • Python数据结构与算法之链表,无序链表详解
    目录我们首先来构造节点。节点(Node)的类构建完毕后,接下来我们开始构建整个链表(LinkList)的类。那么我们还需要一个方法来判断链表头的指向。接下来我们构建链表节点的添加方法...
    99+
    2024-04-02
  • Java数据结构顺序表用法详解
    目录1.什么是顺序表2.顺序表的基本功能和结构3.顺序表基本功能的实现和解析1.判断线性表是否为空2.获取指定位置的元素3.向线性表表添加元素4.在位置i处插入元素5.删除指定位置的...
    99+
    2024-04-02
  • Java数据结构与算法的示例分析
    这篇文章给大家分享的是有关Java数据结构与算法的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。第1章 数据结构与算法基础概述1.1 数据结构和算法的重要性算法是程序的灵魂,优秀的程序可以在海量数据计算时...
    99+
    2023-06-29
  • python数据结构的排序算法
    目录十大经典的排序算法 一、交换排序1、冒泡排序(前后比较-交换)2、快速排序(选取一个基准值,小数在左大数在右)二、插入排序1、简单插入排序(逐个插入到前面的有序数中)2、希尔排序(从大范围到小范围进行比...
    99+
    2022-06-02
    python 排序算法 python数据结构
  • Java 数据结构深入理解ArrayList与顺序表
    目录一、ArrayList简介二、ArrayList的使用1、ArrayList的构造2、ArrayList的遍历3、ArrayList的常见操作(方法)4、ArrayList的扩容...
    99+
    2024-04-02
  • Python篇——数据结构与算法(第六部分:哈希表)
      目录 1、直接寻址表 2、直接寻址表缺点 3、哈希 4、哈希表 5、解决哈希冲突 6、拉链法 7、常见哈希函数 8、哈希表的实现 8.1迭代器iter()和__iter__ 8.2str()和repr() 8.3代码实现哈希表 8.4哈...
    99+
    2023-09-10
    python 数据结构 算法 哈希算法
  • JavaScript中数据结构与算法之检索算法的示例分析
    这篇文章主要为大家展示了“JavaScript中数据结构与算法之检索算法的示例分析”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“JavaScript中数据结构与...
    99+
    2024-04-02
  • python数据结构与算法(3)
    Python内置类型性能分析 timeit模块timeit模块可以⽤来测试⼀⼩段Python代码的执⾏速度。class timeit.Timer(stmt='pass', setup='pass', ...
    99+
    2023-01-31
    数据结构 算法 python
  • Java数据结构之顺序表的实现
    目录前言一、顺序表1.1 什么是顺序表二、简单实现顺序表2.1 创建顺序表2.2 打印顺序表2.3 获取顺序表长度2.4 在 pos 位置新增元素2.5 判定是否包含某个元素2.6 ...
    99+
    2024-04-02
  • Python数据结构与算法之跳表详解
    目录0. 学习目标1. 跳表的基本概念1.1 跳表介绍1.2 跳表的性能1.3 跳表与普通链表的异同2. 跳表的实现2.1 跳表结点类2.2 跳表的初始化2.3 获取跳表长度2.4 ...
    99+
    2024-04-02
  • 【数据结构与算法】堆与堆排序
    目录 一.堆的实现1.堆的概念2.堆的代码实现二.堆排序的讲解 一.堆的实现 1.堆的概念 堆是一种数据结构,首先它总是一颗完全二叉树(因为堆适合表示完全二叉树),在逻辑上堆是一颗...
    99+
    2023-09-04
    php 开发语言 原力计划
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作