【数据结构汇总】

绪论

数据结构三要素
逻辑结构(线性/非线性)、物理结构(顺序/链式/索引/散列)、数据运算
算法定义
由基本运算及规定的运算顺序所构成的完整的解题步骤
算法的特性
有穷性、确定性、可行性、输入、输出
算法设计目标
正确性、可读性、健壮性、高效率和低存储需求
算法效率的度量
时间复杂度:基本运算语句在算法中被重复执行的次数。
空间复杂度:该算法所耗费的存储空间。
数据的物理存储
1)顺序存储:把逻辑上相邻的元素存储在物理位置上也相邻的存储单元中,元素之间的关系由存储单元的邻接关系来体现。其优点是可以实现随机存取,每个元素占用最少的存储空间;缺点是只能使用相邻的一整块存储单元,因此可能产生较多的外部碎片。
2)链式存储:不要求逻辑上相邻的元素在物理位置上也相邻,借助指示元素存储地址的指针来表示元素之间的逻辑关系。其优点是不会出现碎片现象,能充分利用所有存储单元;缺点是每个元素因存储指针而占用额外的存储空间,且只能实现顺序存取。
3)索引存储:在存储元素信息的同时,还建立附加的索引表。索引表中的每项称为索引项,索引项的一般形式是(关键字,地址)。其优点
是检索速度快;缺点是附加的索引表额外占用存储空间。另外,增加和删除数据时也要修改索引表,因而会花费较多的时间。
4)散列存储:根据元素的关键字直接计算出该元素的存储地址,又称哈希(Hash)存储。其优点是检索、增加和删除结点的操作都很快;缺点
是若散列函数不好,则可能出现元素存储单元的冲突,而解决冲突会增加时间和空间开销。(线性探测法、平方探测法、链地址法)
递归
(1)什么是递归:函数定义过程中调用自身的方法
(2)递归调用的实现原理
系统首先为递归调用建立一个工作栈,其结构包括值参、局部变量和返回地址;
每次执行递归调用之前,把递归函数的值参和局部变量的当前值以及调用后的返回地址压栈
每次递归调用结束后,将栈顶元素出栈,使相应的值参和局部变量恢复为调用前的值,然后转向返回地址指定的位置继续执行
(3)递归算法的设计
将暂且不能解决的大问题分成许多子问题,子问题还是不能解决则继续划分,直到子问题小到可以直接解决的规模,原问题的解即子问题解的合并
(4)递归算法到非递归算法的转换
利用栈保存参数,由于栈的后进先出特性吻合递归算法的执行过程,因而可以用非递归算法替代递归算法。
(5)递归的优缺点
递归算法解题通常显得很简洁,但运行效率低,在递归调用的过程中系统用栈来存储每一层的返回点、局部量,递归次数过多容易造成栈溢出等问题。

线性表

顺序表和链表
顺序表可以顺序存取也可以随机存取,链表只可以顺序存取;顺序表便于查找、修改元素,链表便于增加删除元素;采用顺序表存储时逻辑上相邻的元素物理上也相邻,采用链式存储时逻辑上相邻的元素物理上不一定相邻;链式存储空间分配灵活。
栈和队列
栈只允许在队尾进行元素的插入删除操作,队列允许在一端进行插入、另一端进行删除操作;队列先进先出,栈先进后出;
共享栈
利用栈底位置相对不变的特性,可以让两个顺序栈共享一个一维数组空间,将两个栈的栈底分别设置在共享空间的两端,两个栈顶向共享空间的中间延伸。这样能够更有效的利用存储空间,两个栈的空间相互调节,只有在整个存储空间被占满时才发生上溢。

基本概念由0个或多个字符组成的有限序列
串的模式匹配对一个串中某子串的定位操作称为串的模式匹配。
(1)简单模式匹配
从主串的第一个位置起和模式串的第一个字符开始比较,如果相等则继续逐一比较后续字符,否则从主串的第二个字符开始重新用上一步的方法与模式串中的字符作比较,以此类推直到比较完模式串中的所有字符,若匹配成功则返回模式串在主串中的位置,匹配不成功则返回一个可区别于主串所有位置的标记
(2)KMP算法 时间复杂度为O(m+n)
是一种改进的字符串匹配算法,算法核心是利用匹配失败后的信息尽量减少模式串与主串的匹配次数以达到快速匹配的目的,具体实现就是通过如果已匹配相等的前缀序列中有某个后缀正好是模式的前缀,那么就可以将模式向后滑动到与这些相等字符对齐的位置,主串i指针无须回溯,并继续从该位置开始进行比较。而模式向后滑动位数的计算仅与模式本身的结构有关,与主串无关。
(3)KMP算法的优点:(1)减少了匹配次数(2)主串指针不需要回溯,则可以将对外存中较大规模的字符串的匹配操作分段进行,先读入一部分进内存进行匹配,完成之后即可写回外存,当发生不匹配时不需要将之前写回外存的部分重新读入,减少了I/O操作,提高了执行效率
广义表
广义表是一种特殊的线性表,她的元素可以是也可以是广义表。广义表的第一个元素称为广义表的表头,其余元素称为广义表的表尾。广义表的长度指表中最上层元素的个数,深度指括号的最大层数。

结点的度节点所拥有分支的个数
树的度节点度的最大值
满二叉树除最后一层外其他结点均有两棵子树
完全二叉树完全二叉树是指除了最后一层外,其他任何一层的结点数均达到最大值,且最后一层也只是在最右侧缺少结点
树的存储结构
双亲表示法:采用连续的存储空间存储结点,并为每个结点设置一个伪指针指向双亲结点在数组中的位置
孩子表示法:为每个结点建立一个单链表,单链表内存储该结点的所有孩子结点
孩子兄弟表示法:以二叉链表作为存储结构,结点由三部分组成,结点值、指向第一个孩子的指针、指向下一个兄弟的指针
哈夫曼树
给定n个带权值的结点,将其看做N个子树,从最小的两棵子树开始,为其创建一个父节点,父节点的权值即两棵子树的权值之和,将这颗新的树放回集合中参与新一轮的合并,直至所有结点被合并至一棵树,这棵树即哈夫曼树,哈夫曼树的特点就是带权路径最短,不含度为1的结点,n个原始结点构成的哈夫曼树共2n+1个结点
二叉排序树
左子树若存在则左子树的关键字均小于根结点,右子树若存在其值均大于根节点,同时左右子树又是一棵二叉排序树。
平衡二叉树
左右子树高度之差不超过1的二叉排序树
线索二叉树
为了方便找到某结点在某种遍历中的前驱后继节点,n个结点n+1个空链域
树转换为二叉树
将父节点相同的结点串联,从左至右除第一个节点外断开各节点与父节点的联系,调整结构
森林转化为二叉树
先将各树转换为二叉树,再将第二棵二叉树作为第一棵二叉树的右子树,第三棵二叉树作为第二棵二叉树的右子树,直至合并为一棵树
树的遍历
先根=二叉树先序
后根=二叉树中序遍历
哈夫曼树
哈夫曼树是带权路径最短的树,给定n个权值,将其看做n个只有根节点的子树,选取权值最小的两棵子树为其分配根节点,根结点的权值为两棵子树权值之和,从原森林中删除两棵子树,将新生成的树放入其中,重复上述步骤直至只有一颗子树。
哈夫曼树中没有度为1的结点,所有权值点均是叶子结点,结点总数2n+1
哈弗曼编码
对哈夫曼树中的每个节点进行编号,左0右1,进而得到整个字符串的编码,每个字符的权值是出现的次数,出现次数越多距离根节点越近,字符编码长度越短
树的层次遍历
建立一个循环队列,将二叉树的根节点入队,然后出队访问该节点,若有左子树则左子树入队,又右子树则右子树入队,如此反复直至队列为空
先序遍历
建立一个栈,根节点入栈,栈不空,则出栈并将其左右孩子入栈(先右后左),重复出栈入栈过程直至栈空
中序遍历
根节点入栈,左孩子存在则入栈,不存在则出栈栈顶元素,然后检查右孩子,右孩子存在则入栈,栈空时结束
后序遍历
定义两个栈,根节点入栈1,只要栈1不为空,出栈栈顶元素入栈2,左孩子存在则左孩子入栈1,右孩子存在则右孩子入栈1,重复出栈1入栈2操作直至栈1为空,此时只要栈2不空,则出栈并访问栈顶元素

存储结构
邻接矩阵、邻接表
邻接多重表、十字链表
邻接矩阵:用一维数组存储点信息,二维数组存储边信息,该二维数组称为邻接矩阵,适合稠密图
邻接表:顺序存储与链式存储相结合,为每个顶点建立一个单链表,无向图的链表内存储与该顶点有边相连的顶点,有向图中存储由该顶点指向或指向该节点的顶点
邻接多重表:由顶点表和边表构成,顶点表由两个域构成(顶点,第一条边),边表(访问位,与a相连的边,a,b与b相连的边),所有依附于同一顶点的边串联在同一链表中,每个边结点同时链接在两个链表中,对无向图而言,同一条边在邻接表中用两个结点表示,而在邻接多重表中只需一个结点
图的遍历
(1)深度优先遍历DFS
首先访问出发点,将其标记为已访问,选取与该节点邻接的未访问过的顶点w访问并标记,再选取与w相邻接未访问的节点重复此操作。当一个顶点的所有邻接结点都被访问过时,退回到最近被访问过的节点,若该节点仍有未被访问的节点则重复访问过程,直至图中所有节点都被访问过为止。
(2)广度优先遍历BFS
首先访问起始顶点v,然后依次访问所有与v相邻的节点w1,w2…,再依次访问w1、w2所有相邻节点,直至图中所有顶点都被访问过为止
最小生成树(无向图)
(1)普利姆算法 O(n2)
从图中任取一个顶点,把它当作一棵树,从这棵树相接的边中选取权值最小的边,并将这条边及其所连接的顶点并入这颗树中,此时再从与这棵树相接的边中选取一条最短的边,并将这条边及其所连接的顶点并入这棵树中,直至所有顶点都被并入树中。
(2)克鲁斯卡尔算法
将图中的边按权值从小到大排序,从最小边开始扫描各边,若当前边的并入不会构成回路则将其并入生成树中,直至所有的边都被检测完为止。适用于稀疏图
最短路径(有向图)
(1)迪杰斯特拉 某一顶点到其余各顶点的最短路径 O(n2)
设置两个顶点集合S和T,S中存放已找到最短路径的顶点,T中存放剩余顶点,初始时S中只有源点。
不断从集合T中选取到源点路径长度最短的顶点并入S中,S中每并入一个新的顶点,都要修改源点到集合T中顶点的最短路径长度,重复此过程直至T中顶点全部并入S中为止。
(2)弗洛伊德 图中任意一对顶点的最短路径 O(n3)
设置两个矩阵A和Path,将图的邻接矩阵赋给A,Path全部设置为-1
以顶点k(个数为0~n-1)为中间节点,对图中所有顶点对(i,j)进行检测:
若由i至j经过中转节点k的路径长度小于当前路径长度,则对Path进行更新,否则什么都不做
拓扑排序
从有向图中选取选取一个无前驱结点的顶点输出,从图中删除该顶点并删除由该顶点出发的全部边,重复上述步骤直至图中不存在没有前驱的顶点为止
关键路径
求出拓扑序列a和逆拓扑序列b,根据序列a b分别求出每个事件的最早发生时间和最迟发生时间,根据上述结果再倒推求出每个活动的最迟发生时间和最早发生时间,找出最早发生时间和最迟发生时间相同的活动,即为关键活动,由关键活动连接成的路径即关键路径。

排序

直接插入排序:从无序序列中选取待排关键字插入有序序列中的适当位置
折半插入排序:设置三个变量low,high,mid,其中mid=(low+high)/2,当关键字>mid位置的值时,low=mid+1否则high=mid-1,直至low>high,将low到最后一个位置的元素都向后移一位,空出位置插入关键字
希尔排序:将序列划分为若干个子序列,在子序列中进行直接插入操作,然后再对所有子序列进行直接插入操作
冒泡排序:将元素两两比较,逆序则交换,一趟结束后最大的值会来到序列最后的位置,此时一趟冒泡完成,重复直至某一趟未发生数据交换
快速排序:选择一个关键字作为枢纽,将序列中比枢纽小的关键字移至前方,比枢纽大的关键字移至后方,将序列以枢纽为中心划分为两个子序列,在对两个子序列进行同样的操作,直至每个子序列的长度为1,序列有序。
简单选择排序:从无序序列中选择最小的关键字与无序序列中的第一个关键字进行交换。
堆排序:将序列中所有关键字组成一个完全二叉树,若满足树中根节点均不大/小于左右子节点,则此树的根节点为最大/小关键字。
归并排序:将两个或两个以上的有序表合并成新的有序表

在这里插入图片描述
不稳定:快希选堆
nlog2n:快归堆

查找

线性
顺序查找:在表头设置哨兵,将待排关键字放入哨兵位置,从表尾元素向前进行对比,若找到则返回下标为止,若返回0则表示查找失败
折半查找:要求查找表为顺序存储结构且表中元素有序,当low>high时停止查找
分块查找:块间有序,块内无序,根据索引表定位块,在块中进行顺序查找
树形
二叉排序树:将关键字与根节点进行比较,若小于根节点则去左子树中查找,若大于根节点则去右子树中查找,若指针来到空链域则表示查找失败
二叉平衡树:左右子树高度之差不大于1,且左右子树也都是平衡二叉树
散列结构
散列表:通过把关键码的值映射到表中的一个位置以加快查找速度。
解决冲突:开放定址法(线性探测、平方探查)、链地址法

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值