数据结构1--定义、分类

一、程序设计=数据结构+算法

1、数据结构:数据元素相互之间存在一种或者多种特定关系的集合。

数据结构:逻辑结构和物理结构

逻辑结构:数据对象中数据元素之间的相互关系。

集合结构:同属于一个集合。之外没有其他关系。

线性结构:数据元素之间是一对一的关系。

树形tree结构:数据元素之间存在一对多的层次关系。(可看成一种特殊的图)

图形map结构:数据元素之间存在多对多的层次关系。

物理结构:数据的逻辑结构在计算机中的存储形式。

顺序存储(元素放在地址连续的存储单元)

链式存储(元素存放在任意存储单元,用指针存放元素地址)

2、算法

解决特定问题求解步骤的描述,在计算机中表现为指令的有限序列,并且每条指令表示一个或多个操作

算法的五个基本特征:输入、输出、有穷性、确定性、可行性

 算法具有零个或多个输入。

 算法至少有一个或多个输出。输出形式可以是打印形式,也可以是返回值。

 有穷性:算法执行有限的步骤之后,自动结束而不会无限循环。并且每一个步骤在可接受的时间内完成。

 确定性:算法的每一个步骤都具有确定的含义,不会出现二义性。算法在一定条件下只有一条执行路径,相同的输入只能有唯一的输出结果。算法的每个步骤都应该被精确定义而无歧义。

 可行性:算法的每一步都必须可行,每一步都能够通过执行有限次数完成。【否则必须注明执行所要求的环境】

算法设计的要求:

正确性:算法至少应该具有输入、输出和加工处理无歧义性,能正确反映问题的需求、得到正确答案。大体分为以下四个层次:

 A没有语法错误

 B对合法输入能产生满足要求的输出

 C对非法输入能产生满足规格的说明

 D对故意刁难的测试输入都有满足要求的输出结果

可读性:算法得便于阅读、理解和交流。写代码的目的,一方面是为了让计算机执行,另一方面也得便于他人阅读和自己日后阅读修改。

健壮性:输入数据不合法时,算法也能做相关处理,而不是产生异常、崩溃或其他莫名其妙的结果。

时间效率高&存储量低

3、时间复杂度

1)算法的运行时间与什么相关?
取决于输入的数据。(例如:如果数据已经是排好序的,时间消耗可能会减少。)
取决于输入数据的规模。(例如:6 和 6 * 109)
取决于运行时间的上限。(因为运行时间的上限是对使用者的承诺。)
算法分析的种类:

最坏情况(Worst Case):任意输入规模的最大运行时间。(Usually)
平均情况(Average Case):任意输入规模的期待运行时间。(Sometimes)
最佳情况(Best Case):通常最佳情况不会出现。(Bogus)
例如,在一个长度为 n 的列表中顺序搜索指定的值,则

最坏情况:n 次比较
平均情况:n/2 次比较
最佳情况:1 次比较
而实际中,我们一般仅考量算法在最坏情况下的运行情况,也就是对于规模为 n 的任何输入,算法的最长运行时间。这样做的理由是:

一个算法的最坏情况运行时间是在任何输入下运行时间的一个上界(Upper Bound)。
对于某些算法,最坏情况出现的较为频繁。
大体上看,平均情况通常与最坏情况一样差。
算法分析要保持大局观(Big Idea),其基本思路:

忽略掉那些依赖于机器的常量。
关注运行时间的增长趋势。
比如:T(n) = 73n3 + 29n3 + 8888 的趋势就相当于 T(n) = Θ(n3)。

渐近记号(Asymptotic Notation)通常有 O、 Θ 和 Ω 记号法。Θ 记号渐进地给出了一个函数的上界和下界,当只有渐近上界时使用 O 记号,当只有渐近下界时使用 Ω 记号。尽管技术上 Θ 记号较为准确,但通常仍然使用 O 记号表示。

使用 O 记号法(Big O Notation)表示最坏运行情况的上界。例如,

线性复杂度 O(n) 表示每个元素都要被处理一次。
平方复杂度 O(n2) 表示每个元素都要被处理 n 次。

4、算法的空间复杂度

写代码时可以用空间来换取时间。(互换)

(闰年的两种方式

A算法来写,每次判断

B事先建立2050的数组,闰年为1,不是则0直接查表,浪费空间)

空间复杂度通过计算算法所需的存储空间实现,计算公式:S(n)=O(f(n)),其中n为问题的规模,f(n)为语句关于n所占存储空间的函数。

**数据类型:**是指一组性质相同的值的集合及定义在此集合上的一些操作的总称。

要计算入1+1=2这样的整型数字的运算,显然不需要开辟很大的内存空间。

而如果要计算1.23456789+2.987321这样就需要开辟比较大的空间才存放的下。

要对数据类型进行分类,分出多种数据类型来适合各种不同的计算条件差异。

抽象:描述数据类型的方法不依赖于具体实现

抽象数据类型(ADT)是带有一组操作的一些对象的集合。

在ADT定义中没有关于这些操作如何实现的任何解释。

对象集+操作集

二、线性结构

1)如何表示多项式

方法1 :顺序存储结构直接表示

方法2 :顺序存储 结构 表示非零项

数组分量是由系数a i 、指数i组成的结构,对应一个非零项

方法3:链表结构存储非零项

链表中每个 结点存储多项式中的一个 非零项 ,包括 系数和指数两个数据域以及一个

1、数组

数组是可以再内存中连续存储多个元素的结构,在内存中的分配也是连续的,数组中的元素通过数组下标进行访问,数组下标从0开始。例如下面这段代码就是将数组的第一个元素赋值为 1。

优点:
1、按照索引查询元素速度快
2、按照索引遍历数组方便

缺点:
1、数组的大小固定后就无法扩容了
2、数组只能存储一种类型的数据
3、添加,删除的操作慢,因为要移动其他的元素。

适用场景:
频繁查询,对存储空间要求不大,很少增加和删除的情况。

2、链表

链表是物理存储单元上非连续的、非顺序的存储结构,数据元素的逻辑顺序是通过链表的指针地址实现,每个元素包含两个结点,一个是存储元素的数据域 (内存空间),另一个是指向下一个结点地址的指针域。根据指针的指向,链表能形成不同的结构,例如单链表,双向链表,循环链表等。

链表的优点:
链表是很常用的一种数据结构,不需要初始化容量,可以任意加减元素;
添加或者删除元素时只需要改变前后两个元素结点的指针域指向地址即可,所以添加,删除很快;

缺点:
因为含有大量的指针域,占用空间较大;
查找元素需要遍历链表来查找,非常耗时。

适用场景:
数据量较小,需要频繁增加,删除操作的场景

3、队列

队列是限定只能在表的一端进行插入和在另一端进行删除操作的线性表。

1)顺序存储

通常由一个一维数组 和一个记录 队列头元素位置的变量front 以及 一个记录 队列尾元素位置的变量rear 组成 。

2)链式存储

队列 的链式 存储结构 也可以用 一个单链表 实现。插入和删除操作
分别在链表的两头进行;
只能在头部放front

4、栈

栈是一种特殊的线性表,仅能在线性表的一端操作,栈顶允许操作,栈底不允许操作。
栈的特点是:先进后出,或者说是后进先出,从栈顶放入元素的操作叫入栈,取出元素叫出栈。

栈的顺序存储结构通常由一个一维数组 和一个记录栈顶 元素位置的变量组成 。
栈的链式存储结构实际上就是 一个 单链表 ,叫做链栈 。插入和删除操作只能在链栈的栈顶进行。

应用:表达式求值(中缀后缀)
在这里插入图片描述
其他应用:
 函数调用及递归实现
 深度优先搜索
 回溯算法

三、树

在这里插入图片描述

是由一个集合以及在该集合上定义的一种关系构成的。集合中的元素称为树的结点,所定义的关系称为父子关系。树(tree )是 n(n ≥ 0)个结点的有限集。

​ 树中结点的最大层次数称为树的**深度(**Depth **)**或高度。

​ 结点拥有的子树的数目称为结点的度(Degree

​ 度为 0 的结点称为 叶子(leaf )或端结点

​ 如果将树中结点的各子树看成是从左至右是有次序的,则称该树为 有序树;若不特别指明,一般讨论的树都是有序树。

​ 树中所有结点最大度数为 m 的有序树称为 m 叉树

A、 二叉树

参考 https://www.jianshu.com/p/912357993486

1、二叉树

1)定义
每个结点至多拥有两棵子树(即二叉树中不存在度大于2的结点),并且,二叉树的子树有左右之分,其次序不能任意颠倒。
2)二叉树的性质
1.若二叉树的层次从0开始,则在二叉树的第i层至多有2^i个结点(i>=0)
2.高度为k的二叉树最多有2^(k+1) - 1个结点(k>=-1)(空树的高度为-1)
3.对任何一棵二叉树,如果其叶子结点(度为0)数为m, 度为2的结点数为n, 则m = n + 1

3)二叉树又分为:完美二叉树,完全二叉树,完满二叉树
4)二叉树的遍历方法
先序遍历:即根-左-右遍历
中序遍历:即左-根-右遍历
后序遍历:即左-右-根遍历

2、二叉查找树

1)定义

二叉查找树也称为有序二叉查找树,满足二叉查找树的一般性质,是指一棵空树具有如下性质:
任意节点左子树不为空,则左子树的值均小于根节点的值
任意节点右子树不为空,则右子树的值均大于于根节点的值
任意节点的左右子树也分别是二叉查找树
没有键值相等的节点

2)局限性及应用

一个二叉查找树是由n个节点随机构成,所以,对于某些情况,二叉查找树会退化成一个有n个节点的线性链.如下图:
在这里插入图片描述

3、AVL树

1)定义

AVL树是带有平衡条件的二叉查找树,和红黑树相比,它是严格的平衡二叉树,平衡条件必须满足(所有节点的左右子树高度差不超过1).不管我们是执行插入还是删除操作,只要不满足上面的条件,就要通过旋转来保持平衡,而旋转是非常耗时的

2)使用场景:

AVL树适合用于插入删除次数比较少,但查找多的情况。
也在Windows进程地址空间管理中得到了使用
旋转的目的是为了降低树的高度,使其平衡

3)AVL树特点:

AVL树是一棵二叉搜索树
AVL树的左右子节点也是AVL树
AVL树拥有二叉搜索树的所有基本特点
每个节点的左右子节点的高度之差的绝对值最多为1,即平衡因子为范围为[-1,1]

4、红黑树

1)定义

一种自平衡二叉查找树, 通过对任何一条从根到叶子的路径上各个节点着色的方式的限制,红黑树确保从根到叶子节点的最长路径不会是最短路径的两倍,用非严格的平衡来换取增删节点时候旋转次数的降低,任何不平衡都会在三次旋转之内解决

2)使用场景:

红黑树多用于搜索,插入,删除操作多的情况下
红黑树应用比较广泛:
1.广泛用在C++的STL中。map和set都是用红黑树实现的。
2.著名的linux进程调度Completely Fair Scheduler,用红黑树管理进程控制块。
3.epoll在内核中的实现,用红黑树管理事件块
4.nginx中,用红黑树管理timer等

原因:
红黑树的查询性能略微逊色于AVL树,因为比AVL树会稍微不平衡最多一层,也就是说红黑树的查询性能只比相同内容的AVL树最多多一次比较,但是,红黑树在插入和删除上完爆AVL树,AVL树每次插入删除会进行大量的平衡度计算,而红黑树为了维持红黑性质所做的红黑变换和旋转的开销,相较于AVL树为了维持平衡的开销要小得多

3)性质:
1.节点是红色或黑色。
2.根节点是黑色。
3.每个叶子节点都是黑色的空节点(NIL节点)。
4 每个红色节点的两个子节点都是黑色。(从每个叶子到根的所有路径上不能有两个连续的红色节点)
5.从任一节点到其每个叶子的所有路径都包含相同数目的黑色节点。

B、多叉树

B树
B-tree 树即 B 树,B 即 Balanced,平衡的意思。

  1. B 树通过重新组织节点, 降低了树的高度.
  2. 文件系统及数据库系统的设计者利用了磁盘预读原理,将一个节点的大小设为等于一个页(页得大小通常为 4k), 这样每个节点只需要一次 I/O 就可以完全载入
  3. 将树的度 M 设置为 1024,在 600 亿个元素中最多只需要 4 次 I/O 操作就可以读取到想要的元素, B 树(B+)广泛 应用于文件存储系统以及数据库系统中

0、2-3树和2-3-4树

2-3树是最简单的B-树(或-树)结构,其每个非叶节点都有两个或三个子女,而且所有叶都在统一层上。
在这里插入图片描述

1、B树

1)定义

B-树就是B树,-只是一个符号.
B树(B-Tree)是一种自平衡的树,它是一种多路搜索树(并不是二叉的),能够保证数据有序。同时它还保证了在查找、插入、删除等操作时性能都能保持在O(logn),为大块数据的读写操作做了优化,同时它也可以用来描述外部存储(支持对保存在磁盘或者网络上的符号表进行外部查找)
在这里插入图片描述

2)特点:

在这里插入图片描述

1、关键字集合分布在整颗树中;
2、任何一个关键字出现且只出现在一个节点中;
3、每个节点存储date和key;
4、搜索有可能在非叶子节点结束;
5、一个节点中的key从左到右非递减排列;
6、所有叶节点具有相同的深度,等于树高h。

2、B+树

1)定义

B+树是B-树的变体,也是一种多路搜索树
B+的搜索与B-树也基本相同,区别是B+树只有达到叶子结点才命中(B-树可以在非叶子结点命中),其性能也等价于在关键字全集做一次二分查找;
在这里插入图片描述

2)B+的特性:

1.所有关键字都出现在叶子结点的链表中(稠密索引),且链表中的关键字恰好是有序的
2.不可能在非叶子结点命中
3.非叶子结点相当于是叶子结点的索引(稀疏索引),叶子结点相当于是存储(关键字)数据的数据层
4.更适合文件索引系统
原因: 增删文件(节点)时,效率更高,因为B+树的叶子节点包含所有关键字,并以有序的链表结构存储,这样可很好提高增删效率

3)使用场景:

文件系统和数据库系统中常用的B/B+ 树,他通过对每个节点存储个数的扩展,使得对连续的数据能够进行较快的定位和访问,能够有效减少查找时间,提高存储的空间局部性从而减少IO操作。他广泛用于文件系统及数据库中,如:
Windows:HPFS 文件系统
Mac:HFS,HFS+ 文件系统
Linux:ResiserFS,XFS,Ext3FS,JFS 文件系统
数据库:ORACLE,MYSQL,SQLSERVER 等中
详见另一篇博客 mysql索引

4)比较

B树:有序数组+平衡多叉树
B+树:有序数组链表+平衡多叉树(数据都在叶子节点,io次数少,更稳定)

B*树(扩展)
在这里插入图片描述

四、散列表(hash表)

通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。

![在这里插入图片描述](https://img-blog.csdnimg.cn/20210127201504177.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM1ODQxNjM3,size_16,color_FFFFFF,t_70)

五、堆

堆中某个节点的值总是不大于或不小于其父节点的值;
堆总是一棵完全二叉树。

将根节点最大的堆叫做最大堆或大根堆,根节点最小的堆叫做最小堆或小根堆。常见的堆有二叉堆、斐波那契堆等。

因为堆有序的特点,一般用来做数组中的排序,称为堆排序。

六、图

图是由结点的有穷集合V和边的集合E组成。其中,为了与树形结构加以区别,在图结构中常常将结点称为顶点,边是顶点的有序偶对,若两个顶点之间存在一条边,就表示这两个顶点具有相邻关系。

按照顶点指向的方向可分为无向图和有向图

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值