数据结构:数据用什么样的方式组合在一起
数据存储的常用结构有:栈、队列、数组、链表和红黑树
栈
stack,又称堆栈。
栈只有一个出口,且先进后出(想象一下弹夹),只能从出口位置操作元素,不能从中间位置操作。
队列
queue,队列,先进先出。(想象一下火车过山洞)
数组
使用连续的内存来存储、数组中的所有元素都是相同的类型或类型的衍生(同质数据结构)、元素可以通过下标(索引)
直接访问
特点是:查询快(有索引),增删慢
指定索引位置增加元素:需要创建一个新数组,将指定新元素存储在指定索引位置,再把原数组元素根据索引,复制到新数组对应索引的位置
链表 LinkedList
单向链表
增删快(把两个节点断开,插入新的节点就可以了),查询慢
链表本身是无序的。
由两部分组成:数据域和指针域,每个结点都有一个指针,每个节点指针的指向都是指向自身结点的下一个结点,最后一个结点的head指向为null,对单链表的操作只能从一端开始
,如果需要查找链表中的某一个结点,则需要从头开始进行遍历。
双向链表 doubly-linked-list
对于双向链表来说,它的每个节点要指向“直接前驱”和“直接后继”
,所以节点类需要含有两个指针域
。指向直接前驱的指针使用pre
表示,指向后继的指针使用next
表示。双向链表是在单向链表基础上的一个改进,每个节点指向其直接前驱和直接后继节点。因此,从双向链表的任意位置开始,都能访问所有的节点。同时也可以保证元素存入和取出的顺序是一致的
。
双向链表从节点的结构上可以看出,双向链表的所需的存储空间大于单向链表
。同时,对于插入和删除等操作来说,双向链表的节点操作更加复杂,涉及到节点的前后两个节点。
二叉树 binary tree
二叉树是每个节点最多有两个子树的树结构。顶上的叫根结点,两边被称作“左子树”和“右子树”。
红黑树
红黑树可以通过红色节点和黑色节点尽可能的保证二叉树的平衡,从而来提高效率。
图片上的字实在是太小了,为方便以后好看,在下面写一下吧
-
第二张图
排序时,查找时
在二叉树的基础上,元素是有大小顺序的
左子树元素小,右子树元素大平衡树
它的左右两个子树的高度差的绝对值不超过1,
并且左右两个子树都是一棵平衡二叉树 -
第三张图左边
不平衡树
高度差值大于1
注意:
在动态插入过程中如果需要保证树的完美平衡,代价过高
但是我们又想要保证查询速度快,那么尽量要保证二叉树的平衡 -
第三张图右边
红黑树
趋近于平衡树,查询的速度非常快
查询叶子节点的最大次数和最小次数不能超过2倍红黑树的约束:
1.根节点/空节点是黑色的,其他节点可以是红色的或者黑色的
2.每个红色节点的子节点都是黑色的
3.任何一个节点到其每一个叶子节点的所有路径上黑色节点数相同通过红黑树的约束
保证最大路径不超过最小路径的2倍,来尽量保证红黑树的平衡
哈希表
哈希表
(hash table,也叫散列表),是根据关键码值(key value)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫散列函数,存放记录的数组叫散列表。
实际上哈希表就是模拟的数组,只不过数组中的每一个元素又是链表。
在Java中,像HashSet,HashMap等集合的底层数据结构都使用了哈希表,哈希表利用了数组支持按照下标访问的特性,因此散列表类似于一种数组的扩展,在JDK1.8及以后,它由数组+链表/红黑树
构成。
哈希表的优势在于:查询速度快,不需要从头开始差,而只需要通过key的值去定位数据所在的链表(Java集合中的hashmap,hashset底层都是通过这样一个哈希表来实现的)。
数组更利于元素的查找;
链表更利于元素的插入和删除;
希表是由一块地址连续的数组空间构成的,其中每个数组都是一个链表,数组的作用在于快速寻址查找,链表的作用在于快速插入和删除元素,因此,哈希表可以被认为就是链表的数组。
!重点:如何判断新增的两个元素是否重复
比较两个对象的哈希值&&(地址值相同||equals相同)
新增过程:
-
计算新增元素的哈希值(hashcode)
-
通过hash%数组长度获取索引值(0-15)
-
如果该位置为null,则直接新增
如果该位置不为null,则判断是否重复(equals());
-
如果不重复则新增到该索引值位置链表的最后面
-
如果重复则不新增
-
哈希表的扩容:当哈希表被占的位置比较多的时候,出现哈希冲突的概率也就变高了,所以很有必要进行扩容。
newCapacity = oldCapacity+(oldCapcity>>1)
新容量等于旧容量的1.5倍
哈希表的内存结构示意图
在散列表中,不像普通数组,每个格子里存放的是一个单一的数据,而是在每一个格子中存放的是一个链表。如图:
JDK1.8 的哈希冲突解决方案
JDK1.8
中的哈希表是使用链表+红黑树
解决哈希冲突。
默认使用单向链表将元素串起来。
每次都是从头节点开始遍历;单向链表比双向链表少一个指针,可以节省内存空间。
在添加元素时,可能会由单向链表转为红黑树
来存储元素。
比如当哈希表容量 ≥ 64 且 单向链表的节点数量大于 8 时。
当红黑树节点数量少到一定程度时,又会转为单向链表。
简单算法
二分查找
二分查找(Binary Search)是一种在有序
数组中查找特定元素的搜索算法。它的工作原理是通过不断地将搜索范围缩小一半来找到目标元素。具体步骤如下:
首先,从数组的中间元素开始搜索。
如果中间元素正好是要查找的元素,则搜索过程结束。
如果某一特定元素大于中间元素,则在数组的右半部分继续搜索。
如果某一特定元素小于中间元素,则在数组的左半部分继续搜索。
重复以上步骤,直到找到目标元素或者搜索范围为空(即找不到目标元素)。
二分查找的时间复杂度是O(logn),其中n是要搜索的数组的大小。这是因为每次比较都会将搜索范围缩小一半,因此查找的次数与log2(n)成正比。这种算法在处理大量数据时具有较高的效率。
二分查找的实现可以涉及多种编程语言,例如C#、Java等。代码示例展示了如何在C#中实现二分查找算法。此外,二分查找也被称为折半查找
或对数搜索,这些名称都指的是同一种算法,只是在不同的语境或文献中表述不同。
部分内容转载自:
https://www.cnblogs.com/joion/p/13646815.html
https://blog.csdn.net/sheng0113/article/details/122781495
https://juejin.cn/post/6976994044928851975
理解历史人物,就是理解现在的人物。
当年明月