数据结构与算法绪论

基本概念和术语

  • 数据

数据是信息的载体,是描述客观事物属性的数,字符以及所有能输入到计算机中并被计算机程序识别和处理的符号的集合。

  • 数据元素

数据元素是数据的基本单位,通常作为一个整体进行考虑和处理。一个数据元素可由若干个数据项组成,数据项是构成数据元素的不可分割的最小单位。例如,学生记录就是一个数据元素,它由学号、姓名、性别等数据项组成。

  • 数据对象

数据对象是具有相同性质的数据元素的集合,是数据的一个子集。例如,整数数据对象是集合 \(N = \lbrace 0, \pm 1, \pm 2, \cdots \rbrace\)

  • 数据类型

数据类型是一个值的集合和定义在此集合上一组操作的总称。

(1)原子类型:其值不可再分的数据类型。

(2)结构类型:其值可以再分解为若干成分的数据类型。

(3)抽象数据类型:抽象数据组织和与之相关的操作。

  • 抽象数据类型

抽象数据类型是指一个数学模型以及定义在该模型上的一组操作。抽象数据类型的定义仅取决于它的一组逻辑特性,而与其在计算机内部如何表示和实现无关,即不论其内部结构如何变化,只要它的数学特性不变,都有不影响其外部的使用。通常用(数据对象、数据关系、基本操作集)这样的三元组来表示抽象数据类型。

  • 数据结构

在任何问题中,数据元素都不是孤立存在的,而是在它们之间存在着某种关系,这种数据元素相互之间的关系称为结构。数据结构是相互之间存在的一种或多种特定关系的数据元素集合。数据结构包括三方面的内容:逻辑结构、存储结构和数据的运算。数据的逻辑结构和存储结构时密不可分的两个方面,一个算法的设计取决于所选定的逻辑结构,而算法的实现依赖于所采用的存储结构。

数据的逻辑结构

逻辑结构是指数据元素之间的逻辑关系,即从逻辑关系上描述数据。它与数据的存储无关,是独立于计算机的。

划分方法一

(1)线性结构

有且仅有一个开始和一个终端结点,并且所有结点都最多只有一个直接前趋和一个后继。

例如:线性表、栈、队列、串

(2)非线性结构

一个结点可能有多个直接前趋和直接后继。

例如:树、图

划分方法二

集合
  • 数据元素间除“同属于一个集合”外,无其它关系

1048215-20190903151124403-185040141.jpg

线性结构
  • 一个对一个,如线性表、栈、队列

1048215-20190903151138650-1716434695.jpg

树形结构
  • 一个对多个,如树

1048215-20190903151203003-1678312594.jpg

图形结构
  • 多个对多个,如图

1048215-20190903151224218-1703360028.jpg

数据的存储结构

存储结构是指数据结构在计算机中的表示(又称映像),也称物理结构。它包括数据元素的表示和关系的表示。数据的存储结构是逻辑结构用计算机语言的实现,它依赖于计算机语言。数据的存储结构主要有:顺序存储、链式存储、索引存储和散列存储。

  • (1)顺序存储:把逻辑上相邻的元素存储在物理位置上也相邻的存储单元里,元素之间的关系有存储单元的邻接关系来体现。其优点是可以实现随机存取,每个元素占用最少的存储空间;缺点是只能使用相邻的一整块存储单元,因此可能产生较多的外部碎片。
  • (2)链接存储:不要求逻辑上相邻的元素在物理位置上也相邻,借助指示元素存储地址的指针表示元素之间的逻辑关系。其优点是不会出现碎片现象,充分利用所有存储单元;缺点是每个元素因存储指针而占用额外的存储空间,并且只能实现顺序存储。
  • (3)索引存储:在存储元素信息的同时,还建立附加的索引表。索引表中的每一项称为索引项,索引项的一般形式是:(关键字,地址)。其优点是检索速度快;缺点是增加了附加的索引表,会占用较多的存储空间。另外,在增加和删除数据时要修改索引表,因而会花费较多额时间。
  • (4)散列结构:根据元素的关键字直接计算出该元素的存储地址,又称为 Hash 存储。其优点是检索、增加和删除结点的操作都很快;缺点是如果散列函数不好可能出现元素存储单元的冲突,而解决冲突会增加时间和空间开销。

数据的逻辑结构是以面向实际问题的角度出发的,只采用抽象表达方式,独立于存储结构,数据的存储方式有多种不同的选择;而数据的存储结构是逻辑结构在计算机上的映射,它不能独立于逻辑结构而存在。数据结构包括三要素,缺一不可。

算法的特性

算法是对特定问题求解步骤的一种描述,它是指令的有限序列,其中每一条指令表示一个或多个操作。此外,一个算法还具有下列 5 个重要特性。

(1)有穷性: 一个算法必须总是(对任何合法的输入值)在执行有穷步之后结束,且每一步都可在有穷时间内完成。

(2)确定性: 算法中每一条指令必须有确切的含义,读者理解时不会产生二义性。即对于相对的输入只能得出相同的输出。

(3)可行性: 一个算法是可行的,即算法中描述的操作都是可以通过已经实现的基本运算执行有限次来实现的。

(4)输入 : 一个算法有零个或者多个的输入,这些输入取自于每个特定的对象的集合。

(5)输出 : 一个算法有一个或者多个输出,这些输出是同输入有着某种特定关系的量。

通常设计一个“好”的算法应考虑达到以下目标。

(1)正确性:算法应当能够正确地解决求解问题。

(2)可读性:算法应当具有良好的可读性,以助于人民理解。

(3)健壮性:当输入非法数据时,算法也能适当地做出反应或进行处理,而不会产生莫名其妙的输出结果。

(4)效率与低存储量需求:效率是指算法执行的时间,存储量需求是指算法执行过程中所需要的最大存储空间,
这两者都与问题的规模有关。

算法效率的度量

算法效率的度量是通过时间复杂度和空间复杂度来描述的。

1、时间复杂度

一个语句的频度是指该语句在算法中被重复执行的次数。算法中所有语句的频度之和记作 \(T(n)\),它是该算法问题规模 n 的函数,时间复杂度主要分析 \(T(n)\)数量级。算法中的基本运算的频度与\(T(n)\)同数量级,所以通常采用算法中基本运算的频度 \(f(n)\) 来分析算法的时间复杂度。因此,算法的时间复杂度记为:\(T(n)=O(f(n))\)

上式中 O 的含义是 \(T(n)\) 的数量级,其严格的数学定义是:若 \(T(n)\)\(f(n)\) 是定义在正整数集合上的两个函数,则存在正常数 \(C\)\(n_0\) ,使得\(n>=n_0\)时,都满足 \(\color{red}{0<=T(n)<=C*f(n)}\) 。其中 \(f(n)\)\(T(n)\) 的一个渐近函数。

算法的时间复杂度不仅依赖于问题的规模 n,也取决于待输入数据的性质。

例如 在数组 \(A[0, \cdots, n-1]\) 中,查找定值 k 的算法大致如下:

i = n - 1;
while(i>=0 && (A[i] != k))i--;
return i;

此算法中的语句(3)(基本运算)的频度不仅与问题规模有关,还与输入实例中 A 的各元素取值及 k 的取值有关:

(1)若 A 中没有与 k 相等的元素,则语句(3)的频度\(f(n) =n\)

(2)若 A 中的最有一个元素等于 k,则语句(3)的频度\(f(n)\) 是常数 0。

最坏时间复杂度是指在最坏情况下,算法的时间复杂度。

平均时间复杂度是指所有可能输入实例在等概率出现的情况下,算法的期望运行时间。

最好时间复杂度是指在最好情况下,算法的时间复杂度。

一般总是考虑在最坏情况下的时间复杂度,以保证算法的运行时间不会比它更长。

在分析一个程序的时间复杂性时,有以下两条规则:

  • 加法规则

\(T(n)=T1(n)+T2(n)=O(f(n))+O(g(x))=O(max(f(n),g(n)))\)

  • 乘法规则

\(T(n)=T1(n) \times T2(n)=O(f(n)) \times O(g(x))=O(f(n) \times g(n))\)

常见的渐近时间复杂度

  • 常量复杂度 \(O(1)\)
  • 对数复杂度 \(O(logn)\)
  • 线性复杂度 \(O(n)\)
  • 平方复杂度 \(O(n^2)\)
  • 指数复杂度 \(O(2^n)\)

基本的复杂度如上,基于以上的表达式可以有很多的组合,其中 \(logn\) 默认情况下等同于 \(log_{2}n\)

大小关系:

\(O(1) < O(log_2n) < O(n) < O(nlog_2n) < O(n^2) < O(n^3) < O(2^n) < O(n!) < O(n^n)\)

2、空间复杂度

算法的空间复杂度\(S(n)\)定义为该算法所耗费的存储空间,它是问题的规模\(n\)的函数。渐进空间复杂度简称为空间复杂度,记作\(S(n)=O(g(n))\)

一个上机程序除了需要存储空间来存放本身所用指令、常数、变量和输入数据外,也需要一些对数据进行操作的工作单位和存储一些为实现计算所需信息的辅助空间,若输入数据所占空间只取决于问题本身,和算法无关,组只需分析输入和程序之外的额外空间了。

算法原地工作是指算法所需辅助空间是常量,即\(O(1)\)

算法复杂的意义

算法复杂度的分级相当于(高等数学)的无穷大的阶,反映了在规模\(n\)趋于无穷大的过程中,算法代价增长的速度。算法的复杂度越高,其实施的代价随着规模增大而增长的速度越快。

\(example\)

\(斐波那契数列的第n项\)

  • 递归算法
def fib(n):if n < 2:return 1else:return fib(n-1) + fib(n-2)

将参数\(n\)看问题实例的规模,不难看出,计算\(F_n\)的时间代价(考虑求加法操作的次数)大致等于计算\(F_{n-1}\)\(F_{n-2}\) 的时间代价之和。这一情况说明,计算\(F_n\)的时间代价大致等比于斐波那契数\(F_n\)的值。根据已有的结论:

\[ \mathop {\lim }\limits_{n \to \infty } {F_n} = {(\frac{{\sqrt 5 + 1}}{2})^n}=1.618^n \]

可以看到计算\(F_n\)的时间代价按\(n\)值的指数增长。

  • 递推算法
def fib(n):f1 = f2 = 1for k in range(1,n):f1, f2 = f2, f2 + f1return f2

用这个算法计算\(F_n\)的值,循环的工作只做一次,循环需要做\(n-1\)次。每次循环中只执行了几个简单动作,总的工作量(基本操作执行次数)与\(n\)值呈现某种线性关系。

这个例子说明,解决同一问题的不同算法,其计算复杂度的差异很大,甚至具有截然不同的性质。通过分析算法复杂度,可以帮助使用者选择适用的算法;也可能发现已知算法的缺陷,促使人们设法开发更好的算法 。

Python 内置类型性能分析

timeit 模块

timeit 模块可以用来测试一小段 Python 代码的执行速度。

class timeit.Timer(stmt='pass', setup='pass', timer=<timer function>)

Timer 是测量小段代码执行速度的类。

stmt 参数是要测试的代码语句(statment);

setup 参数是运行代码时需要的设置;

timer 参数是一个定时器函数,与平台有关。

timeit.Timer.timeit(number=1000000)

Timer 类中测试语句执行速度的对象方法。number 参数是测试代码时的测试次数,默认为 1000000 次。方法返回执行代码的平均耗时,一个 float 类型的秒数。

list 的操作测试

def test1():l = []for i in range(1000):l = l + [i]
def test2():l = []for i in range(1000):l.append(i)
def test3():l = [i for i in range(1000)]
def test4():l = list(range(1000))from timeit import Timert1 = Timer("test1()", "from __main__ import test1")
print("concat ",t1.timeit(number=1000), "seconds")
t2 = Timer("test2()", "from __main__ import test2")
print("append ",t2.timeit(number=1000), "seconds")
t3 = Timer("test3()", "from __main__ import test3")
print("comprehension ",t3.timeit(number=1000), "seconds")
t4 = Timer("test4()", "from __main__ import test4")
print("list range ",t4.timeit(number=1000), "seconds")# ('concat ', 1.7890608310699463, 'seconds')
# ('append ', 0.13796091079711914, 'seconds')
# ('comprehension ', 0.05671119689941406, 'seconds')
# ('list range ', 0.014147043228149414, 'seconds')

pop 操作测试

x = range(2000000)
pop_zero = Timer("x.pop(0)","from __main__ import x")pop_zero = Timer("x.pop(0)","from __main__ import x")pop_zero = Timer("x.pop(0)","from __main__ import x")pop_zero = Timer("x.pop(0)","from __main__ import x")pop_zero = Timer("x.pop(0)","from __main__ import x")
print("pop_zero ",pop_zero.timeit(number=1000), "seconds")
x = range(2000000)
pop_end = Timer("x.pop()","from __main__ import x")
print("pop_end ",pop_end.timeit(number=1000), "seconds")# ('pop_zero ', 1.9101738929748535, 'seconds')
# ('pop_end ', 0.00023603439331054688, 'seconds')

测试 pop 操作:从结果可以看出,pop 最后一个元素的效率远远高于 pop 第一个元素

list 内置操作的时间复杂度

\[ \begin{array}{lc} Op & O \ Efficiency \\ indexx[\ ] & O(1) \\ index \ assignment & O(1) \\ append & O(1) \\ pop() & O(1) \\ pop(i) & O(n) \\ insert(i, item) & O(n) \\ del \ operator & O(n) \\ iteration & O(n) \\ contain(in) & O(n) \\ get \ slice[x:y] & O(k) \\ del \ slice & O(n) \\ set \ slice & O(n+k) \\ reverse & O(n) \\ concatenate & O(k) \\ sort & O(nlogn) \\ multiply & O(nk) \\ \end{array} \]

从上可以看出 list 大概是顺序表实现。

dict 内置操作的时间复杂度

\[ \begin{array}{lc} Op & O \ Efficiency \\ copy & O(1) \\ get \ item & O(1) \\ set \ item & O(1) \\ del \ item & O(1) \\ contains(in) & O(1) \\ iteration & O(n) \\ \end{array} \]

转载于:https://www.cnblogs.com/oneTOinf/p/11453191.html

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

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

相关文章

Windows10 网络图标消失 连接不上网络 的解决方法

【背景】电脑win10的&#xff0c;下载一个软件重启之后网络图标消失&#xff0c;并且无法联网。 参照此解决方法&#xff1a; 原因&#xff1a; 【Windows Event Log】服务对应的注册表出现问题&#xff0c;导致无法正常启动&#xff0c;进而导致一些依赖于它的联网服务无法正常…

VUE:解决 [Vue warn]: Error in render: “TypeError: item.slice is not a function“ (取部分数据)

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 1. 双重循环中使用 slice方法&#xff0c;报错&#xff1a; [Vue warn]: Error in render: "TypeError: item.slice is not a fun…

在 js 中怎样获得 checkbox 里选中的多个值?(jQuery)

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 思路&#xff1a;利用name属性值获取checkbox对象&#xff0c;然后循环判断checked属性&#xff08;true表示被选中&#xff0c;false表…

VUE项目中 获得多个复选框 checkbox 选中的值(jquery)+ 解决 Uncaught TypeError: Cannot read property ‘push‘ of undefine

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 1. 表格生成后第一列是复选框&#xff0c;效果&#xff1a; 表格是直接循环展示的后台返回数据&#xff0c;代码写法&#xff1a; 2. 得…

[开源] FreeSql.AdminLTE.Tools 根据实体类生成后台管理代码

前言 FreeSql 发布至今已经有9个月&#xff0c;功能渐渐完善&#xff0c;自身的生态也逐步形成&#xff0c;早在几个月前写过一篇文章《ORM 开发环境之利器&#xff1a;MVC 中间件 FreeSql.AdminLTE》&#xff0c;您可以先阅读上一篇文章内容了解来龙去脉&#xff0c;再回到这里…

《小狗钱钱》:理财首先应该有一种强烈的意识

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 《小狗钱钱》读完了。以下是个人觉得很有帮助和启发意义的摘抄。 1) "忽视就是一种认输"。2) 并非困难使我们放弃&#xff0c…

广州驾校考试实际道路考试注意事项(图)

导读&#xff1a;面对实际道路考试时&#xff0c;大家都会有些紧张&#xff0c;因为这个科目不再只是面对场地&#xff0c;而是要面对各种状况和各种车辆&#xff0c;也是获取驾照的最后一个关卡。因此&#xff0c;为了让大家掌握考试的整个流程&#xff0c;网为大家带来科目四…

《 Docker 进阶与实战 》 读书笔记

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 以下内容全文出自书目&#xff1a;《 Docker 进阶与实战 》 1. Docker 定义&#xff1a;一个开源的容器引擎&#xff0c;可以方便地对容…

【转】R语言函数总结

原博&#xff1b;R语言与数据挖掘&#xff1a;公式&#xff1b;数据&#xff1b;方法R语言特征 对大小写敏感通常&#xff0c;数字&#xff0c;字母&#xff0c;. 和 _都是允许的(在一些国家还包括重音字母)。不过&#xff0c;一个命名必须以 . 或者字母开头&#xff0c;并且如…

《趋势的力量》-- 观念决定了个人发展的战略路线(大学生选择专业、就业、考研与否的建议)

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 最近几天看了好几本书&#xff0c;其中这一本个人觉得很有启发意义。于是记录一二。 主体大纲&#xff1a; -------------------------…

中间件 - 初识

中间件 - 初识 ​ 在Java项目实际开发中&#xff0c;我们所使用的ActiveMQ、RibbitMQ、Kafka、Tomcat、WebLogic&#xff0c;这些都可以统称为中间件。 ​ 我们初次去了解&#xff0c;什么是中间件? 一、中间件简介 ​ 什么是中间件&#xff1f; ​ 由于业务、机构和技术是不断…

VUE 解决:Property or method “deleteFun“ is not defined on the instance but referenced during render.

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 1. 一个点击事件报错&#xff1a; Property or method "deleteFun" is not defined on the instance but referenced during…

2014年广州科目三道路驾驶技能考试/广汕路科目三路考系统操作和评判指南

一 上车准备 上车准备操作要点&#xff1a; 绕车一周&#xff0c;观察车辆外观和周围环境&#xff0c;确认安全。 考生绕车一周&#xff0c;检查轮胎气压、轮胎磨损情况、轮胎螺栓有无松动&#xff0c;检查有无漏水、漏油等情况&#xff0c;车辆外观有无凹凸等碰撞情况&…

Bootstrap 中: data-toggle 与 data-target 的作用

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 <buttontype"button"class"update-button"style"width:70px; height:40px;"data-toggle"modal&…

VUE 解决:Method “xxx“ has already been defined as a data property.

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 1.调用方法报错&#xff1a; Method "changePage" has already been defined as a data property. 代码写法&#xff1a; 2…

C# 模拟Windows键盘事件

发送键盘消息 1 [DllImport("user32.dll", EntryPoint "keybd_event", SetLastError true)] 2 public static extern void keybd_event( 3 byte bVk, //虚拟键值 4 byte bScan,// 一般为0 5 int…

CDN 的作用与基本过程

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 技术原理解说也可参见另一文&#xff1a;https://blog.csdn.net/jiangyu1013/article/details/88795690 1.简介 CDN&#xff0c;Content …

CDN(内容分发网络)技术原理

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 1. 前言 Internet的高速发展&#xff0c;给人们的工作和生活带来了极大的便利&#xff0c;对Internet的服务品质和访问速度要求越来越高…

视界云:CDN{内容分发网络} 知识详解

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 CDN 全称:Content Delivery Network或Content Ddistribute Network&#xff0c;即内容分发网络 基本思路&#xff1a; 尽可能避开互联…

更改 nginx 默认端口 ( ubuntu、linux )

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 1. 我想让一个demo 站点直接域名访问&#xff0c;不带端口&#xff0c;所以想用 80 端口启动对应前端工程。 发现 80 被 nginx 占用&a…