数据结构与算法Java(一) 数组与链表

一、 数组

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

特点:支持随机访问,根据下标随机访问的时间复杂度为O(1)插入删除操作的平均时间复杂度为O(n)

注意点警惕数组的访问越界问题,在java中,会做越界检查,越界时会报java.lang.ArrayIndexOutOfBoundsException

ArrayList与数组对比:

  1. ArrayList可以将很多数组操作的细节封装起来(如插入删除操作);
  2. ArrayList支持动态扩容,存储空间不够时,自动扩容为1.5倍;而数组需指定大小,内存不够时会创建更大的空间,将原数据复制过去在插入新数据
  3. ArrayList无法存储基本类型,如int类型需要封装Integer类;数组可以
  4. 当表示多维数组或已知数据大小时,用数组更合适

问题:为什么数组要从0开始计数?

参考回答

1)从数组存储的内存模型上看,计算a[k]的内存模型公式为:a[k]_address = base_address + k * type_size。当数组从1开始计数,每次随机访问数据元素都对了一次减法运算,为优化性能,故从0开始

2)历史原因:C语言用0开始计数数组下标,效仿c语言

 

二、链表

 

 

 

 

1、双向链表对于单链表的优势:(LinkedHashMap容器用到了双向链表)

  1. 插入删除操作:比如在删除给定指针指向的结点的情况下,双向链表不需要遍历查找前驱结点,可以在O(1)的时间复杂度完成操作。
  2. 有序链表查询:查询时可以记录上次查找的位置p,每次查询时,根据要查找的值与p的大小关系,决定往前或是往后查找,所以平均只需要查找一半的数据

2、链表与数组性能对比

1)时间复杂度

  • 数组:插入删除为O(n),随机访问为O(1)
  • 链表:插入删除为O(1),随机访问为O(n)

2)访问效率:数组使用的是连续内存,可以借助CPU的缓存机制预读数据,访问效率 更高;链表使用的是零散的内存块,没法有效预读

3)内存空间:由于数组用的是连续内存,当声明的数组过大时,可能导致内存不足(out of memory),声明的数组过小时,又得申请更大空间,在复制插入,费时;链表支持动态扩容,没有大小限制

3、指针理解:将某个变量赋值给指针,实际上就是将这个变量的地址赋值给指针,或者反过来说,指针中存储了这个变量的内存地址,指向了这个变量,通过指针就能找到这个变量。

注意点

1)警惕指针丢失和内存泄漏

如在单链表中,要在结点a和结点b之间插入结点x,要注意操作顺序,即

x->next=p->next;p->next=x;

2)单链表第一个结点插入操作

if(head==null) {

head = new_node;

}

  删除链表中的最后一个结点

if(head->next = null) {

Head = null;

}

3)留意边界条件:

链表为空时,能否正常工作;链表只有一个节点时,能否正常工作;链表只有两个结点时能否正常工作;头尾结点处理时,能否正常工作

 

 

参考资料:极客时间的《数据结构与算法之美》王争

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值