趣学数据结构笔记
01数据结构基础
数据结构+算法=程序
数据是一切能输入计算机中的信息的总和,结构是指数据之间的关系。
数据结构就是将数据及其之间的关系有效地存储在计算机中并进行基本操作。
算法是对特定问题求解步骤的一种描述,通俗讲就是解决问题的方法和策略。
why学习数据结构
学习有效存储数据的方法、处理具有复杂关系的数据、提高算法效率
数据结构
逻辑结构
集合
线性结构
树
图
存储结构
顺序存储
链式存储
散列存储
索引存储
运算
初始化、查找、取值、插入、删除、遍历等
通过学习数据结构,更加准确和深刻地理解不同数据结构之间的共性和联系,学会选择和改进数据结构,高效地设计并实现各种算法,这才是数据结构的精髓。
02 算法复杂性计算方法
时间复杂度
基本运算的执行次数、渐进时间复杂度
空间复杂度
输入输出、算法本身、辅助空间
03 顺序表
顺序表的静态分配、动态分配
时间复杂度分析:初始化O(1)、取值O(1)、查找O(n)、插入O(n)、删除O(n)
04 链表
单链表
双向链表
05 线性表的应用
有序顺序表合并
有序链表合并
单链表就地逆置
快慢指针大法
06 栈【后进先出】
顺序栈
静态分配、动态分配
链栈
07 队列【先进先出】
顺序队列
静态分配、动态分配、假溢出
循环队列
链队
08 栈和队列的应用
数制转换
回文判定
回文是指正读反读均相同的字符序列,也就是说字符串沿中心线对称。
09 KMP算法
模式匹配:子串的定位运算称为串的模式匹配或串匹配。
10 模式匹配应用——病毒检测
环形字符串模式匹配的求解方法
11 数组的顺序存储
数组是由相同类型的数据元素构成的有限集合。一维数组可以看作一个线性表
12 特殊矩阵的压缩存储
什么是压缩存储?给多个相同的元素分配一个存储空间,元素为0的不分配空间。
什么样的矩阵能够压缩?一些特殊矩阵,如对称矩阵、三角矩阵、对角矩阵又称为带状矩阵、稀疏矩阵等。
什么叫稀疏矩阵?一般非零元素个数小于5%的矩阵为稀疏矩阵。
13 数组应用——好玩贪吃蛇
14 树
● 有序树——节点的各子树从左至右有序,不能互换位置。
● 无序树——节点各子树可互换位置。
● 森林——由m(m≥0)棵不相交的树组成的集合。
树的存储结构
顺序存储分为双亲表示法、孩子表示法和双亲孩子表示法。
链式存储分为双孩子链表表示法和孩子兄弟表示法。
孩子兄弟表示法的秘诀:长子当作左孩子,兄弟关系向右斜。
树转换为二叉树的秘诀:长子当作左孩子,兄弟关系向右斜。
二叉树转换树为的秘诀:左孩子为长子,右斜线为兄弟。
把森林中的每棵树的树根看作兄弟关系,把森林中的每一棵树转换成二叉树,然后把每棵树的根节点连接在右斜线上。
15 二叉树
二叉树的性质
16 二叉树遍历
先序遍历秘籍:访问根,先序遍历左子树,左子树为空或已遍历才可以遍历右子树
中序遍历秘籍:中序遍历左子树,左子树为空或已遍历才可以访问根,中序遍历右子树。
后序遍历秘籍:后序遍历左子树,后序遍历右子树,左子树、右子树为空或已遍历才可以访问根。
层次遍历秘籍:首先遍历第1层,然后第2层……同一层按照从左向右的顺序访问,直到最后一层。
17 树的应用
如果二叉树为空,则深度为0,否则二叉树的深度等于二叉树左右子树的深度最大值加1。
如果二叉树为空,则叶子数为0;如果根的左、右子树都为空,则叶子数为1;其他情况下,二叉树的叶子数等于左子树的叶子数与右子树的叶子数之和。
根据遍历序列可以还原树,包括二叉树还原、树还原和森林还原3种。
二叉树还原:由二叉树的先序序列和中序序列,或者中序序列和后序序列,可以唯一地还原一棵二叉树。
注意:由二叉树的先序序列和后序序列不能唯一地还原一棵二叉树。
18 哈夫曼树
通常的编码方法有等长编码和不等长编码两种。
等长的编码:所有字符的编码长度相等,n个不同的字符需要logn位编码。
不等长编码:经常使用的字符编码较短,不常用的字符编码较长。
最优编码方案是指编码总长度最短。
不等长编码方法需要解决两个关键问题:
1)编码尽可能短。
2)不能有二义性。
哈夫曼编码的核心思想:权值大的叶子离根近。
哈夫曼算法的贪心策略:每次从树的集合中取出没有双亲且权值最小的两棵树作为左右子树,构造一棵新树,新树根节点的权值为其左右孩子节点权值之和,并将新树插入树的集合中。
约定左分支上的编码为“0”,右分支上的编码为“1”。从根节点到叶子节点路径上的字符组成的字符串为该叶子节点的哈夫曼编码
19 图
图的结构比较复杂,任何两个顶点之间都可能有关系。
常用的图存储方法:1)邻接矩阵 2)边集数组
3)邻接表 4)链式前向星
图的遍历根据搜索方式的不同,分为广度优先搜索和深度优先搜索。
广度优先遍历秘籍:先被访问的顶点,其邻接点先被访问。先来先服务,可以借助于队列实现。
深度优先遍历秘籍:后被访问的顶点,其邻接点先被访问。后来先服务,可以借助于栈实现。
Dijkstra 算法是解决单源最短路径问题的贪心算法;时间复杂度:O(n²)。空间复杂度:O(n)。可考虑采用优先队列和邻接表两个方面优化。
Floyd算法可以求解任意两个顶点的最短路径。时间复杂度:O(n3)。空间复杂度:O(n²)。
最小生成树:权值之和最小的生成树,则称为最小生成树。求解最小生成树有两种算法:Prim算法【时间复杂度:O(n²)。空间复杂度:O(n)】、Kruskal算法【时间复杂度:O(eloge)、空间复杂度:O(n)】。两种算法都采用了集合避圈,但算法思想完全不同。
23 关键路径
一个无环的有向图称为有向无环图(Directed Acycline Graph,DAG)。
用顶点表示活动,用弧表示活动之间的优先关系的有向图,称为顶点表示活动的网(Activity On Vertex Network),简称AOV网。
在AOE网中,从源点到汇点的带权路径长度最大的路径为关键路径,关键路径上的活动为关键活动。时间复杂度:O(n+e)。空间复杂度:O(n+e)。
拓扑排序是指将AOV网中的顶点排成一个线性序列,该序列必须满足:若从顶点i到顶点j有一条路径,则该序列中顶点i一定在顶点j之前。
注意:拓扑排序并不是唯一的。
24 顺序表查找
查找(Search),又称为搜索,指从数据表中找出符合特定条件的记录。
查找
线性表查找
顺序查找
折半查找【二分查找】
树表查找
二叉查找树
特性:左子树
平衡二叉查找树【又叫AVL树】
调整平衡的方法:LL旋转、RR旋转
LR旋转:分两次旋转,B做RR旋转,然后A再做LL旋转。
RL旋转:分两次旋转,B做LL旋转,然后A再做RR旋转。
散列表查找
散列表是根据关键字直接进行访问的数据结构。
散列表是根据关键字直接进行访问的数据结构。
散列函数(Hash function),又称为哈希函数,是将关键字映射到存储地址的函数。
常见的散列函数:(1)直接定址法、(2)除留余数法
无论如何设计散列函数,都无法避免冲突问题。如果发生冲突,就需要进行冲突处理。冲突处理方法分为3种:开发地址法、链地址法、建立公共溢出区。
根据增量序列的不同,开放地址法又分为线性探测法、二次探测法、随机探测法、再散列法。
28 排序
快速排序(Quicksort)是比较快速的排序方法。快速排序基于分治策略,分为三步:分解、治理、合并。快速排序是不稳定的排序方法。
堆排序是一种树形选择排序算法。堆排序选择一个关键字最小(最大)的记录只需要O(logn)的时间。时间复杂度:O(nlogn)、空间复杂度:O(1)。不稳定
合并排序是采用分治的策略,将一个大的问题分成很多小问题,再通过小问题解决大问题。时间复杂度:O(nlogn)、空间复杂度:O(n)。稳定
分配排序不需要比较关键字的大小。分配排序包括桶排序和基数排序。基数排序可以看作桶排序的扩展,它是一种多关键字排序算法。
32 并查集
并查集是一种树形数据结构,用于处理一些不相交集合的合并及查询问题。创建并查集只需要三个步骤:初始化、查找、合并
并查集中,合并集合的时间复杂度为O(e*logn)。
33 优先队列
优先队列是利用堆来实现的,堆可以看作一棵完全二叉树的顺序存储结构。
优先队列的两个基本操作:出队、入队
“下沉”:堆顶与左右孩子比较,如果比孩子大,则已满足堆;如果比孩子小,则与较大的孩子交换,交换到新的位置后,继续向下比较,从根节点一直比较到叶子。
“上浮”:新记录与其双亲比较,如果小于等于双亲,则已满足堆;如果比双亲大,则与双亲交换,交换到新的位置后,继续向上比较,从叶子一直比较到根。
出队时,下沉从根到叶子,最多达到树的深度,时间复杂度为 O(logn);
入队时,上浮从叶子到根,最多达到树的深度,时间复杂度也为 O(logn)。
34 B-树
多路平衡搜索树,又称为B-树,或者B树。
B-树具有平衡、有序、多路的特点。
B-树的查找时间包括将节点从外存调入内存和在内存中当前节点查找两个方面。
需要进行分裂操作解除上溢。
下溢处理分为3种情况:左借、右借、合并。
35 B+树
B+树是B-树的变种,更适用于文件索引系统。从严格定义上讲,B+树已经不属于树,因为叶子之间有连接,树是不允许同层节点有连接的。
B+树支持两种方式的查找,可以利用t指针从树根向下索引查找,也可以利用r指针从最小关键字向后顺序查找。
36 红黑树
红黑树在AVL树“适度平衡”的基础上,进一步放宽条件:红黑树的左右子树高度差绝对值不超过两倍。红黑树也是一种平衡二叉搜索树。Java中的集合类TreeMap就是红黑树的实现。
从红黑树与4阶B树的等价关系可以看出:4阶B树中的节点中必然含有一个黑节点,且最多包含3个关键字;
如果包含2个红关键字,则黑关键字必然在中间位置。