数据结构笔记总结

简介: 节点的度:节点的子树个数树的度:树的所有节点中最大的度数叶节点:度为0的节点父节点:有子树的节点是其子树的根节点的父节点兄弟节点:具有统一父节点的节点彼此称为兄弟节点。路径和路径长度:路径所包含边的个数。祖先节点:沿着树根到某一节点路径上的所有节点都是这个节点

数据结构的四种基本逻辑

分类1:线性结构与 非线性结构

线性结构:链表,队列,对,堆栈...

非线性结构:树,图

分类2:四种基本逻辑结构


集合

线性表

存储结构种类

顺序存储结构

链式...

索引...

散列...

顺序存储结构

用一组连续存储单元按照顺序存储

比如数组

链接存储结构

类似于链表,数据元素之间通过指针链接

索引存储方式

存储节点信息的时候附加建立存储表,相当于目录

散列存储方式

根据节点关键字计算出该节点存储地址

线性表

首先,有一类共性问题:有线性序列的组织和管理,我们用线性表来存储线性结构数据

线性表的关键信息:

同种数据类型构成的有序序列

元素个数称为表长度

没有元素称为空表

始末称为表头、表尾

主要含有

数据对象集:n个元素构成的有序序列

操作集:假设 线性表L属于list类型,i表示位置,元素属于数据类型elementtype。

对表的主要操作:


一、线性表的存储实现(利用数组)

思路:定义一个结构体指针,自定义数据类型。内部元素有数组和一个末尾元素的地址。(这就跟上面的衔接起来,这跟链表的节点好像)那个数组是用来存储个数组。




栈的顺序存储实现

一维数组单方向堆栈

栈的顺序存储通常由一个一维数组和一个记录栈顶的位置变量组成。

在这里一维数组代表栈内元素,top代表栈顶元素位置。

注意:top=-1的时候代表空栈,top=0代表栈内有一个元素。

(1)入栈:检验知否堆栈满,如果没满就把元素堆入栈,top值+1。

(1)入栈:先判断堆栈满了没。如果没满,要往第一个堆栈里添加元素,就top1++。要往第二个堆栈添加元素就top2--。

(2)出栈: 先判断是否空栈。再分别进行操作。

表达式在程序中的存储

我们常见的表达式一般是中缀表达式,儿在程序中一般转换为后缀表达式进行存储。

如何把中缀表达式转换为后缀表达式: 数字读下来,遇到运算符号就存储在堆栈中,每一次比较堆栈中运算符的优先级,读入整个表达式之后按运算级最高的进行计算。

不同部分转换方式:

运算数直接输出

左括号压入堆栈

右括号:将栈顶的运算符弹出并输出,直到遇到左括号(出战,不输出)

运算符:若优先级大于栈顶运算符,则压栈;否则将栈顶运算符弹出并输出。再比较新的栈顶运算符,直到该运算符大于栈顶运算符优先级为止,然后将该运算符压栈。

全部处理完毕后把栈中运算符一并输出。

注意:

单独的括号优先级其实比加号低,双括号的运算级是最高的。

读到完整的双括号之后,双括号联通中间的内容都被运用并且取出。之后再继续读入

整个式子就像俄罗斯方块一样从上到下消去。

广义表

广义表是线性表的推广

对于线性表而言,n个元素都是基本的氮元素

广义表中,这些元素不急可以是单元素也可以是另一个广义表。



如图,这是广义表的形象图


树的初识

树:n(n>=0)个节点构成的有限集合;当n=0时称为空树;树有一个称为“根”的特殊节点,其余节点可以分为m个互不相交的有限集,其中每一个集合本身又是一棵树,称为原来的“子树”。


树的一些基本定义

节点的度:节点的子树个数

树的度:树的所有节点中最大的度数

叶节点:度为0的节点

父节点:有子树的节点是其子树的根节点的父节点

兄弟节点:具有统一父节点的节点彼此称为兄弟节点。

路径和路径长度:路径所包含边的个数。

祖先节点:沿着树根到某一节点路径上的所有节点都是这个节点的祖先节点。

树的深度:树中所有节点最大层次是这颗树的深度。

树的表示

二叉树:一个节点有三个东西,一个内容,两个指针。



一些特殊的二叉树

斜二叉树(相当于链表,只有左/右支)


完美二叉树(满二叉树):每个节点的子节点都满2


完全二叉树:每一行从左往右没有空的,但是不一定是完美二叉树。(如下图1是2不是)


树的遍历

一般有四种方法:


先序遍历:根 - 左子树 - 右子树


中序遍历:左子树 - 根 - 右子树


后序遍历:左子树 - 右子树 - 根


层序遍历:从上到下,从左到右


先序遍历


利用一种递归的思想实现遍历



先检验是否为空(即BT)


然后访问左侧,再访问右侧



先序遍历过程图解

中序遍历





中序遍历过程图解


后序遍历




后序遍历过程图解


遍历总结


所有遍历方法都是使用递归的方法


只有先序遍历是从上往下的,其他遍历方法都是从下往上的


如图,×代表先序遍历路径,⭐代表中序遍历,▲代表后序遍历。


二叉树的遍历(非递归)

递归的是指其实还是用堆栈,每一次把数据存储在堆栈中,等判断条件达到终止之后再倒着输出。这样一来,如果需要处理的数据非常庞大,仍然存在空间占用过大的问题,就像前面讲的一样,递归虽然是个效率高的方法,但是存储空间消耗很大,就像飞机一样,虽然速度快但是代价昂贵,而且每次运输数量有限。


中序遍历


遇到一个节点把这个节点压栈,然后沿着这个节点便利左支。


左支遍历结束之后从栈顶弹出这个节点病情访问他。


再按照这个方法遍历右支。




层序遍历




大概原理:(必须遵从这个)


非空左子树的所有值小于根节点值


非空右子树的所有值大于根节点值


左右子树都是二叉搜索树


搜索二叉树

搜索效率可以通过计算平均查找长度(ASL)来判断,其中完全二叉搜索树查找效率最搞,斜二叉树查找效率最低。


(ASL计算方法:就是查找每个元素需要遍历的长度相加,除以结点个数。)


为了提高二叉树查找效率,需要平衡二叉树。


(平衡二叉树(AVL树):平衡因子=|左子树高度-右子树高度|)


调整方法

1.




2.


调整模式主要有四种:rr,ll,rl,lr。(right,left)


一个核心方法就是找到破患者和被破坏这区域附近的大约3个结点(这三个节点的asl指数都不是0),把asl数剧中的系欸但作为根,把asl小的放左侧,大的放右侧。


概述/引入


又名最优二叉树,树的总路径长度最短


可以说是从堆引入的。堆的作用是构造最大堆和最小堆实现挑选最值删除的东西。


原理:出现频率较高的数占空间小,出现频率较低的数占空间更大。从而实现不压缩数据且节省空间的一种存储方式。


哈夫曼树

引:堆的构造是在所有数字中挑选两个最大/最小的数字合并,再继续挑选继续合并。而哈夫曼树是在数据中挑选两个出现频率最低的数进行合并。


在数据中挑选两个出现频率最低的数进行合并


接着选频率最低的数和上一个父结点进行合并得到新的父结点(父结点的值是两个子结点的和)


一直合并完成所有元素


所有元素必须是叶子结点,保证没有歧义(二义性)


这棵哈夫曼树左侧路径都标0,右侧都标1


哈夫曼编码特点

字符只在叶结点上。(作用是避免二义性。保证每一个参数都没有后缀只有前缀(路径上的数就代表前/后缀)


左支是0,右支是1




如此一来,路径所组成的数就是该字符对应的编码。


在数据中挑选两个出现频率最低的数进行合并


注意我们需要的字符都放在叶结点上。


这样编码可以很大几率让频率高的字符编码更短。


计算路径长度


要想计算最优二叉树中某个结点权重的路径长度,方法是每个叶子结点的(该结点权重*到根节点路径数量)相加总和。因为哈夫曼树我们认为叶子结点的值本身就是一种频率,所以结点值就是权重,所以哈夫曼树总路径长度一般是每个(叶子结点值*到根节点长度)相加总和。


因哈夫曼树构建方法就是从第频率到高频率进行合并,所以最长的路径总是对应最低的频率,得到的总路径长度总是最短的,也就是最优的。


集合

并查集:“并”把两个集合并在一起;“查”查某个元素属于哪个集合。


具体作用:现在有很多个集合,每个集合又有很多个元素。我们想查一个元素,需要找这个元素在哪个集合的什么位置,或者想把两个集合合并为一个集合。




(该图只是形象的比喻一下,真正的存储方式并不是这样)


子结点指向父结点,这种方法与二叉树有所不同,这个叫做双亲表示法。


我们把一个集合看作一个树状结构,一个根节点何以被大于两个元素指向,根节点和叶结点都是集合中的元素。


这个并查集存储的就是各个集合的根节点的指针。


集合的表示

每个元素可以用一个结构体类型数组进行表示。


每个结构体内有两个东西:数据域;整型数字(这个元素的父节点在数组中的位置,相当于指针)


具体如何存储呢



data是元素内容;parent是每个元素对应的集合的根节点(如果该元素本身就是根节点,其根节点就用-1表示);下标是各个元素的标签(就是数组下标),因为元素不一定是数字,我们经常用元素下标来查找对应内容。


某几个数组下标代表的元素是根节点,这些根节点的根节点值是-1。而非根节点的元素的根节点值是对应根节点的数组下标。


查找某个元素所在的集合

(每个元素都有一个数组下标,根节点本身也拥有一个数组下标。)


第一遍循环,按照数组下标挨个寻找对应的元素。如果找到了就退出循环并返回数组下标,如果没找到就返回-1(结束这个函数)。


第二次循环,判断条件是相应数组下标的根节点值是否大于0,如果大于0,就让数组下标等于这个根节点值,这个根节点值代表的就是其根节点的数组下标。




集合的并运算

干啥的:告诉你两个元素,你要把这两个元素对应的集合并起来。




程序框架:找到两个元素各自的根节点;判断根节点是否相等;如果相等就不管;如果不相等就把其中一个根节点并入另一个根节点(把一个根节点的parent值改成另一个根节点对应的数组下标数)




这样一来“树”会长高一层,随着合并的进行,这个数可能会越来越高。为了尽可能提高效率,我们尽量把小的集合并入大的集合中。


这样一来,还要判断需合并的两个集合的大小。


为了记录集合中元素个数,我们可以使用一个非常巧妙的方法,把根节点parent值记为其中元素个数的负数。


一些基本概念


无向图/有向图:即途中路径是否有方向。


网络:图的路径上有数字,这些数字称为权重。当图上由权重的时候就叫做网络。


顶点集和边集,一般由二元组表示,和离散一样,但是这里的图不考虑自回路和平行边。


稀疏图:点多边少,矩阵中有大量的0


路径:两点之间结点的集合。路径长度就是路径中边的数量(如果是网络就是所有路上的权重之和)。


简单路径:两点之间路径上所有顶点都不同。


回路:起点等于终点的路径。


连通图:图中任意两点均连通


连通分量:无向图的极大连通子图


强连通:有向图中顶点v和w之间存在双向路径,则称v和w是强连通。


不一定是平行边(事实上程序中不存在平行边),可以通过不同路径,如下图A可以到B,B可以到A




图在程序中表示(邻接矩阵,邻接表)


使用二维数组,两个下标初始化都是结点数-1,接着用两个下标分别表示两个顶点,如果两顶点之间由边则赋值为1,无边则赋值为0。


(假如有9个结点)




邻接矩阵

阐述:邻接矩阵是图的一种存储方式,一般用数组进行存储。有向图一般用二维数组,无向图可以用一维数组。


特点:


左上到右下的数字全是0,因为不允许自回路。


以上面那个对角线为对称轴,如果是无向图,其两侧情况一致,因为两节点之间肯定是情况一致的。这样一来就发现矩阵有一般空间都浪费了,下方进行优化




无向图优化


用一维数组存储。




直接在红色框里从第一行从左到右存储,数组下标是序号,数组值是0/1。


这个方法虽然节省了空间,但是让寻找哪两个点变难了,没办法嘛。


如果是网络的话,把数组值定义为权重就行了。


邻接表


阐述:是图的一种存储方式,利用链表实现。用邻接矩阵存储稀疏图会造成空间浪费,链表的方式解决了这个弊端。


其实不止这两种表示图的方式,用什么方式取决于要解决什么问题。


图的遍历

主要有两种方法:


深度优先搜索DFS,广度优先搜索BFS


深度优先搜索:在一个结点处,望向所有边,优先前往未经过的结点。如果所有邻接点都经过了,就优先原路返回,不会直接去出口。一直返回,指导退回入口。


这个程序很像堆栈。使用递归的方式点亮邻接点,如果这样一来,经过的结点就会按照顺序被压入,如果没有为点亮的邻接点就返回(弹出)上一个。


广度优先搜索BFS:类似于队列的方式实现。把一个起始结点压入队列,弹出这个起始结点,压入这个起始节点的所有邻接点,再挨个弹出这些邻接点,暗处每个邻接点的时候,压入这个邻接点的邻接点(已经压入过队列的不再重复压入),直到压入过所有结点。(下图是伪码描述)




*Enqueue入队


*V算是起始结点的载体,后面会被赋值为弹出结点


*Dequeue出队


*Q队列

相关文章
|
1月前
|
算法 搜索推荐 Java
数据结构与算法(Java篇)笔记--希尔排序
数据结构与算法(Java篇)笔记--希尔排序
|
11天前
|
存储 算法
【单向链表】数据结构——单向链表的介绍与代码实现&笔记
【单向链表】数据结构——单向链表的介绍与代码实现&笔记
|
11天前
|
存储 算法
【树】数据结构——树和二叉树的概念&笔记
【树】数据结构——树和二叉树的概念&笔记
|
14天前
|
算法 Java 索引
12.12_黑马数据结构与算法笔记Java
12.12_黑马数据结构与算法笔记Java
20 1
|
11天前
|
存储 算法 Linux
【内核链表】数据结构——深入理解内核链表的概念和操作&笔记
【内核链表】数据结构——深入理解内核链表的概念和操作&笔记
【循环链表】数据结构——单向循环链表和双向循环链表操作&笔记
【循环链表】数据结构——单向循环链表和双向循环链表操作&笔记
|
1月前
|
存储 机器学习/深度学习 人工智能
【软件设计师—基础精讲笔记8】第八章 数据结构
【软件设计师—基础精讲笔记8】第八章 数据结构
73 0
【数据结构】做题笔记--区间反转链表
【数据结构】做题笔记--区间反转链表
|
1月前
|
算法 搜索推荐 Java
数据结构与算法(Java篇)笔记--快速排序
数据结构与算法(Java篇)笔记--快速排序
|
1月前
|
机器学习/深度学习 算法 搜索推荐
数据结构与算法(Java篇)笔记--归并排序
数据结构与算法(Java篇)笔记--归并排序