第2章 数据结构概述

该部分为学习笔记,具体内容详见:《数据结构(Python语言描述)》一书

第一节 基本概念

一、数据与数据结构

  1. 数据:数据是指所有能够输入计算机中存储并被计算机处理的符号的总称。
  2. 数据元素:是数据集合中的一个“个体”,是数据的基本单位,在计算机程序中通常将其作为一个逻辑整体进行处理。
  3. 数据项:当一个数据元素包含多个部分信息时,其中每个部分的信息被称为数据项。也被称为字段、域或属性。
  4. 数据对象:是性质相同的数据元素的集合,是数据的一个子集。
  5. 数据结构:带关系的数据元素构成的集合称为数据结构。
  6. 逻辑结构:是指数据结构中各数据元素之间的内在关系。包括:线性结构、树形结构、图状结构和集合。
  • 线性结构:普通的线性表、栈和队列等
  • 树形结构:元素之间存在“一对多”的关系,层次型的结构
  • 图状结构:元素之间存在“多对多”的关系
  • 集合:数据元素之间无其他关系
  • :树形结构、图状结构和集合都不属于线性结构,统称为非线性结构。
  • :逻辑结构除了可以用逻辑结构示意图表示之外,还可以用二元组方式来表示。
  1. 存储结构:是指数据结构在计算机中的表示(映像)方法,是逻辑结构在计算机中的存储实现。对数据结构的存储应包含数据元素本身及数据元素之间的关系。包括:顺序存储、链式存储、索引顺序存储、哈希存储。
  • 顺序存储:所有的数据元素存放在一篇连续的存储单元中。
  • 链式存储:每个数据元素在内存中的映像包含元素值和指针域两个部分,被称为结点。每个结点单独分配空间,因此无需占用连续内存。
  • 索引顺序存储:包含两个部分,即主数据表和索引表,其主要用于快速查找数据元素。
  • 哈希存储:也称为哈希表和散列表,通常是一个稀疏顺序表,用于存储集合,目的是提高数据的查找效率

二、数据类型

  1. 数据类型及分类
    按照对象值是否可分解,数据类型也常被分为原子类型和组合类型。
  2. 抽象数据类型
    是指一个数学模型及定义在该模型上的一组操作,简称ADT。

第二节 数据结构课程讨论的内容

程序设计的实质在于解决两个主要问题:一是根据实际问题选择一种好的数据结构;二是设计一个好的算法,而好的算法在很大程度上取决于描述实际问题的数据结构。
数据结构是一门研究现实世界中数据元素的逻辑关系、基本操作以及在计算机中如何存储表示和实现的学科。它以高级语言程序设计为基础,需要一些数学知识作为前导,它也是算法分析、操作系统、软件工程等课程的必修先行课,是一门非常关键的课程。

第三节 算法及性能分析

一、算法

  1. 算法的定义
  • 算法是对特定问题的求解步骤的一种描述,它是指令的有限序列,其中每条指令表示一个或多个操作。
  1. 算法的性质
  • 有穷性:算法必须在执行又穷步骤后结束,而且其中的每个步骤都是有穷的。
  • 可行性:算法的每条指令所对应的操作可以完全机械地进行,并且可在有限的时间、空间资源下完成。
  • 确定性:算法中的每条指令应确切定义,没有歧义,即对于某个确定的输入,算法的执行路径和执行结果都是唯一的。
  • 输入:算法有明确定义的0个或多个输入。
  • 输出:算法有明确定义的1个或多个输出,表示算法的处理结果。
  1. 算法与程序
  2. 算法描述

二、算法分析基础

  1. 算法设计目标
  • 正确性:要求算法能够正确地执行,对于一切合法的输入数据都能够得出满足要求的结果。
  • 可读性:算法应该容易阅读,提高算法可读性的方法有两个:一是给算法添加注释,以方便程序设计者和后续维护人员阅读和差错;二是要注意对函数、变量等对象进行合理命名。
  • 健壮性:算法应具有容错处理的功能,当输入的数据不合法或运行环境改变时,算法都能恰当的做出反应或数据处理。可以通过在算法中增加异常处理语句,对算法进行不断测试与优化,达到算法的健壮性。
  • 高效率:算法的效率分为时间效率和空间效率(执行过程中占用的内存空间少则空间效率高)。
  1. 算法分析
    由于在算法效率中更关注时间效率,算法时间效率的分析方法主要有两种方法:时间性能的事后实验统计与时间性能的事前分析估算。
  2. 时间复杂度及计算方法
    将运行时间是常量时间的操作称为“原操作”,将算法中的所有语句执行的原操作的次数之和 T(n) 作为时间代价量度, T(n) 称为时间函数或时间代价函数。如:数值类型数据的赋值、所有数学运算、原子类型的数据的输入和输出等都是原操作,而判断 x 是否在长度为 n 的列表中的 in 操作不是原操作,它包含了若干次数的值比较操作。具体的时间复杂度计算方法如下:
  • 将所有语句中原操作的执行次数之和作为算法的运行时间函数 T(n)。
  • 忽略时间函数 T(n) 的低次项部分和最高次项的系数,只取时间函数的最高次项,并辅以大 O 记号表示。
  1. 时间复杂度计算的简化方法
    关键操作通常是循环最深层的一个语句,它是算法中执行原操作的次数数量级最高的一个语句。
  2. Python 内置类型基本操作的时间性能
  • 注:list.insert 与 list.append() 的时间复杂度的区别
  • 列表常见操作的时间复杂度
基 本 操 作说 明平均时间复杂度
copy复制O(n)
append在尾部插入O(1)
pop list删除最后一个元素O(1)
pop intermediate删除非尾部位置的元素O(k)
insert插入O(n)
get item元素值的读取O(1)
set item元素值的写入O(1)
delete item删除值为 item 元素O(n)
set slice设置切片(切片长度为 k)O(n + k)
get slice切片 k 个元素O(n)
sort排序O(nlog2n)
multiply乘 kO(nk)
x in s判断 x 是否在表 s 中O(n)
min(s)、max(s)求表 s 的最小值、最大值O(n)
get length求表长O(1)
  • 字典常见操作的时间复杂度
基 本 操 作说 明平均时间复杂度
copy复制O(n)
get item读取元素O(1)
set item写入元素O(1)
delete item删除元素O(1)
iteration遍历O(n)
  1. 常见的时间复杂度及性能排序
  • 常量阶 O ( 1 ) O(1) O(1)
  • 对数阶 O ( l o g m n ) O(log_m n) O(logmn),其中 m 为大于 1 的正常数,例如 O ( l o g 2 n ) O(log_2 n) O(log2n)
  • 线性阶 O ( n ) O(n) O(n)
  • 线性对数阶 O ( n l o g 2 n ) O(nlog_2 n) O(nlog2n)
  • 多项式阶 O ( n m ) O(n^m) O(nm),其中 m 为常数,例如 O ( n 2 ) 、 O ( n 3 ) O(n^2)、O(n^3) O(n2)O(n3)
  • 指数阶 O ( m n ) O(m^n) O(mn),其中 m 为常数,例如 O ( 2 n ) 、 O ( 3 n ) 、 O ( n ! ) O(2^n)、O(3^n)、O(n!) O(2n)O(3n)O(n)
  1. 时间复杂度计算原则
  • 加法原则
  • 乘法原则
  1. 其他情况
  • 时间复杂度与输入实例和参数等相关
  • 摊销时间复杂度
    有点算法会在触发某个条件时做额外的工作,此时可以根据这个条件发生的概率对整个算法进行性能评估,这样得到的时间复杂度称为摊销时间复杂度。
  • 多个问题规模的情况
  1. 空间复杂度

三、同一问题的不同算法

现在设计 4 个不同的算法,判断列表中是否含有重复元素。例如【1,2,1,3】中含有重复元素,【1,2,3】中不含重复元素。

  • 搜索法
  • 排序法
  • 集合法
  • 字典法
  • 性能比较

第四节 上机实验

一、Python 内置类型常见操作的性能验证

  1. 验证 Python 列表按索引取值操作的时间性能为 O ( 1 ) O(1) O(1)
  2. 验证 Python 字典的元素都区和写入操作的时间性能为 O ( 1 ) O(1) O(1)
  3. 验证 Python 列表排序操作的时间性能为 O ( n )   O ( n l o g 2 n ) O(n)~O(nlog_2 n) O(n) O(nlog2n)

二、列表生成方法的性能比较

  1. 设计至少 4 种不同的方法生成长度为 n 的列表,分析各算法的时间复杂度。
  2. 编写程序统计 n 为不同规模时各个算法所花费的时间,对数据进行统计分析,讨论实验数据与理论分析是否一致。

三、变位词判断算法的性能比较

  1. 设计 3 种不同的算法,判断两个给定的字符串是否互为变位词。如果一个字符串是另一个字符串中各字符的重新排列组合,那么这两个字符串互为变位词。为简化问题,假设字符串中的字符由 26 个小写字母组成。算法接受两个字符串作为参数,返回 True 或 False。分析各个算法的时间复杂度。
  2. 设计测试程序,分别调用以上算法,获得绝对运行时间,分析实验数据与理论分析的一致性。提示(为了使实验结果能明显地区分除不同算法的时间性能,应对字符串的长度取不同的值,例如10、100、1000、10000等;为避免人工输入,应设计辅助的程序自动产生随机字符串;为了公平比较算法的性能,请注意 3 个算法的实验输入数据的一致性)

四、哥德巴赫猜想问题

验证哥德巴赫猜想:任何一个大于 2 的偶数均可以表示为两个素数之和。输入一个大于 2 且小于 100000 的偶数 n,输出所有和为 n 的素数对,并给出总的素数对数量。例如,10 可以表示为素数对 3、7 及 5、5 之和,总共有两对素数。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值