最近从网上买了两本书,打算重新巩固和学习一下数据结构,之前上学的时候,曾有幸在老师,朋友的推荐下了解到了小灰的算法之旅这本书,一开始听说是Java语言,还有所顾虑,但真读这本书时,就瞬间被里面生动的图所吸引,所以阅读之后,总结了一下相关知识,希望对大家有所帮助。
数组
先从概念说起,什么是数组?
数组的英文是array,是有限个相同类型
的变量
所组成的有序
集合。数组中每一个变量称为元素
。类似于一个整齐有序的军队,有固定的位置,固定的编号,数组中的每一个元素有自己的下标,从0开始,一直到数组的长度-1.
数组的另一个特点:内存中顺序存储
,很好的实现了逻辑上的顺序表。
链表
链表(linked list)是一个在物理上非连续,非顺序的数据结构,由若干节点组成。它的形式更像是电视中的地下党,通过单线联络的方式,隐秘的传递着各种重要信息。 从单向链表说起:
单项链表每一个节点包含两部分,存放数据的变量data,指向下一个节点的指针next。
private static class Node{
int data;
Node next;
}
复制代码
链表的第一个节点叫头节点,最后一个节点叫尾节点,尾节点的next指向null。 一级一级,单向传递。
那么通过链表的一个节点,怎样快速找到前置节点?
可以采用双向链表,它的每一个节点除了拥有data和next外,还有一个指向前置节点的next指针。
数组VS链表
了解完基础知识后,让我看看他们使用方式,以及从四个方面---增删改查总结一下他们的不同。
数组:元素 ------ 链表:节点
操作 | 数组 | 链表 | 时间复杂度 | 不同 |
---|---|---|---|---|
查找元素/节点 | 根据下标随机读取 | 从头节点开始向后一个一个逐一查找 | O(1)/O(n) | 数组可以直接读取,链表要遍历 |
更新节点/元素 | 直接替换 | 不考虑查找过程,直接把旧数据替换 | O(1)/O(1) | 均可直接替换 |
插入节点/元素 | 1.尾部插入 2.中间插入 3.超范围插入 | 1.尾部插入 2.中间插入 3.头部插入 | O(n)/O(1) | 只要空间允许,能够插入的链表是无穷无尽的,不需要像数组一样考虑扩容问题 |
删除节点/元素 | 与插入过程相反 | 1.尾部删除 2.中间删除 3.头部删除 | O(n)/O(1) | 数组删除时,需要移动元素,链表不需要 |
插入,删除,更新链表时,不考虑查找元素的过程时,对应时间复杂度是表中所展示的那样。
关于二者的使用场景:如果是读取多,写入少,数组的优势较大,如果需要在尾部频繁的插入删除,用链表更合适。
补充:内存是什么?链表和数组在内存中的存储方式
内存是由一个个连续的内存单元组成,每个内存单元都有自己的地址,在这些内存单元中,有些被其他数据占用了,有些是空闲的,数组中的每一个元素都存储在小小的内存单元中,并且元素之间紧密排列,既不能打乱元素的存储顺序,也不能跳过某个内存单元存储。链表采用见缝插针的方式,链表的每一个节点分布在内存中的不同位置,依靠next指针关联起来。
复制代码