文章目录
数据结构
数据结构是计算机存储、组织数据的方式。数据结构是指相互之间存在一种或者是多种特定关系的数据元素集合。一般有逻辑结构、存储结构:
- 逻辑结构:反映数据元素之间的逻辑关系,逻辑关系是指数据元素之间前后件之间的关系,与存储位置是没有关系的
- 存储结构:在计算机空间里面的存储方式,一般是顺序存储、链式存储、索引存储、哈希存储等
- 物理结构:数据逻辑结构在计算机存储空间的一种存放形式,也可以说是数据结构在计算机中的映射,一种数据结构可以有多种存储方式
常用的数据结构可以分为四大类:
- 集合:除了在一个集合中,没有什么关系
- 线性结构:一对一的关系
- 树形结构:一对多的关系
- 图形结构:多对多的关系
数组
概念
数组可以连续存储多个元素的数据结构,在内存中的分配也是连续的,可以通过元素的下标来访问元素,下标都是从0开始的
优点
- 按照索引快速查询元素
- 按住索引遍历数组很方便
缺点
- 数组大小恒定
- 只能储存一种类型的数据结构
- 添加和删除操作比较慢
适应场景
频繁查询、对储存空间要求不大,很少有添加和删除的情况
常用操作(golang实现)
golang
在golang语言中,有一个内置的数据结构切片,可以实现可变数组长度。
但是在golang语言中,一个数组就是一个数据的实体对象,使用该变量就是使用了该数组,它是值类型。而对于切片来说确实引用传递。
golang 切片
如果数组的占用的内存过多时,此时通过值传递给函数,就会消耗很大的内存空间,如果传递的是指向数组的指针,如果原指针发生了改变,那么函数里面的指针指向也会跟着发生改变。
所以这个时候如果用切片传递数组参数的时候,就会既能处理好节约内存的问题,又能很好的达到共享内存的问题。
但是也是存在着反例的,切片的底层数组可能会在堆上分配内存,而且小数组在栈上copy消耗也未必会比make消耗的大。
栈
栈是一种特殊的链表,但是只是对线性表的一端进行操作,栈顶允许操作,栈底不允许操作。栈的特点就是:先进后出,后进先出。
从栈顶进入叫做入栈,取出元素叫做出栈
应用场景
大都用来实现递归操作,比如斐波那契数列
常用操作(golang实现)
队列
队列也是线性表的一种,但是从一端加入元素,从另一段取出元素,也就是先进先出。
加入元素,被称为入列,取出元素为出队。
使用场景
多线程阻塞队列中经常使用到
常用操作(golang实现)
链表
链表是物理储存单元上非连续的、非顺序的存储结构,数据元素的逻辑顺序是通过链表的指针地址来实现,每一个元素都包含着两个节点,一个是储存元素的数据域,另一个是指向下一个节点地址的指针域。根据指针的指向,链表能形成不同的结构,单链表、
双链表、循环链表等
优点
- 链表是很常用的一种数据结构,不需要初始化容量,可以任意加减元素
- 添加或者是删除元素只需要改变两个元素结点的指针域指向的地址就可以了
缺点
- 包含大量的指针域。占用的空间比较大
- 查找元素的时候需要遍历链表,非常耗时
使用场景
数据量比较小、需要频繁增加和删除操作的时候
常用操作(golang实现)
散列表
散列表也称为hash表,根据码和值(key和value)直接进行访问的数据结构,通过key和value来映射到集合中的一个位置,这样就可以快速定位到集合中元素。
位图
- 特殊的散列表
- 位的映射
- 应用(快速排序、快速去重、快速查询)
布隆过滤器
- 位图的拓展
- 当一个元素被加入集合时,通过k各散列函数将这个元素映射成一个位数组中的k个点,并将k个点全部置为1
- 存在误判(不存在一定不存在,存在不一定存在):和哈希函数的个数和位图的大小有关
堆
堆是一种比较特殊的数据结构,可以被看作一棵树的数组对象,具有以下的性质:
- 堆中的某个节点的值总是不大于活着不小于其父结点的值
- 堆是一个完全二叉树
- 插入一个数据的时候,我们把新插入的数据放在数组的最后,然后从下往上对话;删除堆顶数据的时候,我们把数组中最后一个元素放在对丁,然后从上往下堆化
- 根节点最大的堆叫做最大堆或者大根堆,根结点最小的堆叫做最小堆或者是小根堆。常见的堆有二叉堆、斐波那契堆
堆排序和快排
- 堆排序数据访问的方式没有快速排序友好,跳着访问的,对cpu不友好
- 对于同样的数据,在排序过程中,堆排序算法的数据交换次数要多于快速排序
堆的应用场景
- 优先级队列
- 求topk(静态数据:维护一个k的小顶堆,依次比较logk)
- 求动态数据的中位数
常用操作(golang)
图
在图形的结构中,结点之间关系可以是任意的,图中任意两个元素之间都可能相关:
- 有向图
- 无向图
图的储存结构
邻接矩阵
表示顶点之间相邻关系的矩阵
- 优点:容易实现图的操作,判断顶点间是否有边
- 缺点:对稀疏图浪费空间
邻接表
一种顺序分配与链式分配相结合的储存方法,它包括两部分:一部分是单链表,用来存放边的信息;另一部分是数组,主要用来存放顶点本身的数据信息
- 优点:空间利用率很高,容易找到顶点的相邻节点
- 缺点:判断两个顶点间是否有弧,需要搜索两个顶点对应的单链表
逆领接表
为了解决邻接表的缺点,查找入度需要遍历顶点对应的边
十字链表
是有向图的另一种链式储存的结构,可以看成是将有向图的邻接表和逆邻接表结合起来得到的一种链表。
在十字链表中,每条弧和每个顶点分别对应着一个结点
邻接多重表
无向图的另一种链式储存的结构,邻接多重表和十字链表一样,每条边和每个顶点分别对应着一个顶点
图的遍历
深度优先搜索(DFS)
- 回溯思想
- 借助栈来实现
广度优先搜索(WFS)
- 地毯式层层推进
- 借助队列来实现
树
一棵树是有n个元素组成的有限集合,其中:
- 每个元素被称为一个结点
- 有一个特定的节点,成为根结点或者根
- 除了根结点之外的其余节点被分成m个互不相交的有限集合,每个子集都是一棵树,被称为原树的子树
他的每一个节点可以有零个或者是多个后继的节点,但有一个且只有一个前驱节点(根结点除外),这些数据节点按分支关系组织起来,清晰地反映了数据元素之间的层次关系
二叉树
二叉查找树
平衡二叉树
平衡查找树之AVL树
平衡二叉树之红黑树
B树
B+树
B*树
trie树
小记
- 一定熟练掌握常用的数据结构和其存储结构
- 熟练掌握常用数据结构的常用操作
- 熟练掌握,可以手撕一些常用的排序算法和查找算法