数据结构-数组&链表

数组

数组Array是一种线性表数据结构,它使用一组连续的内存空间来存储一组具有相同类型的数据。

线性表:数据之间具有简单的前后关系,排列成线一样的结构,每个数据最多只有前后两个方向。数组、链表、队列、栈 都是线性表结构。

( 非线性表:数据之间不是简单的前后关系。树、图、堆等。)

查找

连续的内存空间:可以通过寻址公式计算出该元素存储的内存地址。

因此数组支持随机访问,根据下标随机访问的时间复杂度是O(1)
(不是所有查找时间复杂度都是O(1),只有根据下标是。二分查找复杂度是O(logN))

插入和删除

数组为了保持内存的连续性,会导致插入、删除操作相对比较低效。

插入:如果在末尾插入元素,就不需要移动数据,时间复杂度O(1);如果在开头插入元素,所有的数据都要依次向后移动一位,时间复杂度O(n);平均情况为O(n)

删除:和插入相似,删除第k个位置的数据,也需要移动数据保证内存的连续性。平均复杂度O(n)

异常

数组越界java.lang.ArrayIndexOutOfBoundsException

    public static void main(String[] args) {
        int[] arr = new int[3];
        arr[3] = 5;
    }

运行结果

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 3
	at Test.main(Test.java:30)

原因是数组长度为3,数组下标从0开始,arr[3]已经不在arr数组范围内了。

容器与数组

容器类,例如:ArrayList
ArrayList的优势在于封装了许多数组操作的细节,例如插入删除方法,还可支持动态扩容。
ArrayList不能存储基本类型,如int、long等,需要使用包装类integer、Long等,而自动拆装箱也是有一定的性能消耗的,如果对性能消耗非常敏感,可以使用数组。
如果已知数据大小,且数据操作简单,可以使用数组。

其他

问:为什么大多数编程语言中,数组从0开始编号,而不是从1呢?
答:从存储内存模型来看,下标位置同时也包含了数组偏移的含义。
如果数组从0开始计数,a[0]就是数组的首地址位置,a[k]就是偏移k个元素大小的位置,即:a[k]_addr = base_addr + k * type_size;
如果数组从1开始计算,那么a[k]_addr = base_addr + (k-1)*type_size;
k-1对于cpu来说就增加了一道减法指令。
(也有可能是习惯问题,C语言设计就是从0开始的。)

数组的遍历

// for循环遍历
	int[] arr = {1,2,3,4,5};
	for(int i=0; i<arr.length; i++){
		sout(arr[i]);
	}
//TODO 迭代器遍历

Leecode


链表

上一节中表明了,数组是需要一块连续的内存空间来训相互的,堆内存要求较高。
而链表,则是通过“指针”讲一组零散的内存块关联起来。

单链表

其中我们将内存块成为链表的“结点(或节点)”,
而为了将结点串连起来,每个结点除了存储数据外还要记录下一个结点的地址,通常称记录下一个结点地址的指针为后继结点next

头结点:第一个结点
尾结点:最后一个结点,尾结点中的next是一个空对象null,表示最后一个结点。

操作

链表支持数据的查找、插入、删除等操作。
链表的插入删除只需要考虑到相邻结点指针的改变,所以通常复杂度是O(1)。
而在查找的时候由于无法根据寻址进行随机访问,所以需要从头结点依次向下寻找,通常时间复杂度是O(n)。

循环链表

循环链表是在单链表的基础上,尾结点的后继结点指向了头结点,像环一样首尾相连,所以称作循环链表。

双向链表

单链表只有一个方向,也只有后继结点next指向后面的结点地址。而双向链表支持向前向后两个方向,除了后继结点next,还有前驱结点prev来指向前面的结点地址。

操作

当我们想要删除指定结点的前驱结点时,单链表由于只能向下寻找,所以为了找到前驱结点,我们需要从头遍历链表,直到p->next=q,说明p是q的前驱结点,而这个时间复杂度平均是O(n)。
但是对于双向链表来说,它直接指向了前驱结点,所以只需要p->prev就能得到p的前驱结点,时间复杂度是O(1)。

双向循环链表

在双向链表的基础上,头结点的前驱结点指向尾结点,尾结点的后继结点指向头结点。

基于链表实现LRU缓存淘汰算法

LRU-最近最少使用策略

Leecode

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值