《数据结构》顺序表ArrayList
创始人
2024-01-29 07:31:47
0

《数据结构》顺序表ArrayList

文章目录

  • 《数据结构》顺序表ArrayList
    • 什么是顺序表:
    • 模拟实现顺序表(以int类型为例)
    • 详解ArrayList:
        • ArrayList实现的接口:
        • ArrayList的构造方法:
          • 对源码的解析:
      • ArrayList的方法
      • ArrayList的扩容机制
    • ArrayList的缺陷

什么是顺序表:

顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储,在数组上完成数据的增删查改。

顺序表通过控制数组中的有效数据个数,进而包装成一个连续存储数据元素的线性结构.

模拟实现顺序表(以int类型为例)

import java.util.*;
class MyArraylist{public int size;public int[] elem;MyArraylist(){elem = new int[0];}MyArraylist(int n){elem = new int[n];}private boolean isfull(){return size==elem.length;}private boolean checkpos(int pos){if(pos<0||pos>=size){return false;}return true;}public boolean isempty(){return size==0;}public void display(){for(int i = 0;i < size;i++){System.out.print(elem[i]+" ");}}public void add(int x){if(isempty()){elem = new int[10];}if(isfull()){elem = Arrays.copyOf(elem,elem.length*2);}elem[size] = x;size++;}public void add(int x,int pos){if(isempty()){elem = new int[10];}if(isfull()){elem = Arrays.copyOf(elem,elem.length*2);}if(checkpos(pos)){for(int i = size;i>pos;i--){elem[i] = elem[i-1];}elem[pos] = x;size++;}else{System.out.println("pos下标不合法");}}public boolean contains(int tofind){if(isempty()){System.out.println("顺序表为空,查找失败");}for(int i = 0;i < size;i++){if(elem[i]==tofind){return true;}}return false;}//返回数值k的下标public int indexOf(int k){if(isempty()){System.out.println("顺序表为空,查找失败");}for(int i = 0;i < size;i++){if(elem[i]==k){return i;}}return -1;}//得到pos下标的值public int get(int pos){if(!checkpos(pos)){System.out.println("pos下标不合法");}return elem[pos];}public void set(int x,int pos){if(!checkpos(pos)){System.out.println("pos下标不合法");}else{elem[pos] = x;}}public void remove(int k){if(!checkpos(k)){System.out.println("pos下标不合法");}else{for(int i = k;ielem[i] = elem[i+1];}size--;}}public int size(){return size;}public void clean(){size = 0;}
}
public class Main{public static void main(String[] args){MyArraylist arraylist = new MyArraylist();arraylist.add(1);arraylist.add(2);arraylist.add(1);arraylist.add(2);arraylist.add(1);arraylist.add(2);//arraylist.display();arraylist.add(3,2);arraylist.display();arraylist.remove(2);arraylist.display();}
}

值得注意的是:

在我们的remove和clean方法中,如果删除的元素是引用类型时,需要把这个要被删除的元素置为null,防止出现内存泄露的问题.一般而言,对于pos指针不合法,或者顺序表为空无法查询的情况,我们也可以通过抛出异常来终止本次操作并提醒程序员.

详解ArrayList:

ArrayList实现的接口:

在这里插入图片描述

  1. ArrayList实现了RandomAccess接口,表明ArrayList支持随机访问

  2. ArrayList实现了Cloneable接口,表明ArrayList是可以clone的

  3. ArrayList实现了Serializable接口,表明ArrayList是支持序列化的

  4. ArrayList不是线程安全的,可以在单线程使用.

ArrayList的构造方法:

  • ArrayList()

  • ArrayList(Collection c) 利用其他 Collection 构建 ArrayList

  • ArrayList(int initialCapacity) 指定顺序表初始容量

对源码的解析:

对于ArrayList():

在这里插入图片描述

在这里插入图片描述

我们可以很明显的得出,使用ArrayList构造出来的顺序表,底层是一个空数组,没有容量.

对于ArrayList(Collection c):

在这里插入图片描述

首先.这个构造方法会将接受的c转化为数组存入elem中,并且如果该数组的大小为空,则直接生成一个空数组来作为底层数组,如果不为空 这会判断这个数组是不是一个Object数组,如果是一个Object数组,则不需要进行拷贝了,已经赋值成功了,如果不是一个Object数组,则需要进行拷贝.

对于ArrayList(int initialCapacity)
在这里插入图片描述

作用比较单一 ,传入的int是多大,那么底层数组的容量就是多大.

ArrayList的方法

方法解释
boolean add(E e)尾插 e
void add(int index, E element)将 e 插入到 index 位置
boolean addAll(Collection c)尾插 c 中的元素
E remove(int index)删除 index 位置元素
boolean remove(Object o)删除遇到的第一个 o
E get(int index)获取下标 index 位置元素
E set(int index, E element)将下标 index 位置元素设置为 element
void clear()清空
boolean contains(Object o)判断 o 是否在线性表中
int indexOf(Object o)返回第一个 o 所在下标
int lastIndexOf(Object o)返回最后一个 o 的下标
List subList(int fromIndex, int toIndex)截取部分 list

ArrayList的扩容机制

为了ArrayList的动态存储,对于数组的长度采用的动态扩容的机制.

源码

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

重点关注grow()

private void grow(int minCapacity) {
// 获取旧空间大小int oldCapacity = elementData.length;
// 预计按照1.5倍方式扩容int newCapacity = oldCapacity + (oldCapacity >> 1);
// 如果用户需要扩容大小 超过 原空间1.5倍,按照用户所需大小扩容if (newCapacity - minCapacity < 0)newCapacity = minCapacity;
// 如果需要扩容大小超过MAX_ARRAY_SIZE,重新计算容量大小if (newCapacity - MAX_ARRAY_SIZE > 0)newCapacity = hugeCapacity(minCapacity);
// 调用copyOf扩容elementData = Arrays.copyOf(elementData, newCapacity);
}
private static int hugeCapacity(int minCapacity) {
// 如果minCapacity小于0,抛出OutOfMemoryError异常if (minCapacity < 0)throw new OutOfMemoryError();return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE;
}

在确保数组已经无法存下元素之后,并且用户需要扩容的数值没有问题的情况下,grow保证了ArrayList的动态扩容机制

  • 初步预估按照1.5倍大小扩容

  • 如果用户所需大小超过预估1.5倍大小,则按照用户所需大小扩容

  • 真正扩容之前检测是否能扩容成功,防止太大导致扩容失败

实现了ArrayList 的1.5倍扩容

ArrayList的缺陷

  • 顺序表中间/头部的插入删除,时间复杂度为O(N)

  • 增容需要申请新空间,拷贝数据,释放旧空间。会有不小的消耗

相关内容

热门资讯

适合新手的15个小本创业好项目... 没经验也可以创业,关键你要选对项目,新手能做的创业项目有哪些呢?不仅火爆,而且低成本?一起来看看吧!...
2018年穷人专区 看完让你慌... 创业并不一定是缺钱,也有可能是不满足于现状,不过对于大多数人来说,创业确实是一个摆脱贫困的方法。当然...
2018年几个能赚大钱的小本创... 据分析,目前广州市面旗袍的价格大约在200元到5000元之间。由于穿旗袍的人具有一定的消费能力,所以...
五大2019小本创业首选项目小... 2019小本创业项目有哪些呢?创业首先就是要确定一个好的创业项目,有了好的创业项目创业就会事半功倍,...
适合白手起家的6个 适合白手... "生活中有很多不为人知的冷门生意,只要你胆子大,也许你就可以靠它们发家!很多人对于创业只是空有想法,...
【15年创业好项目】15年创业... 为什么穷人多不敢去创业蛋糕创业蛋糕店创业30岁女人创业做什么适合女性创业的大学生适合什么创业毕业生如...
0加盟费用的小本创业项目有哪些... 加盟商开展加盟主要有2个目的:1、通过加盟来赚取更多利润,其中费用会涉及到,加盟费或者代理费,设备费...
小本创业加盟什么项目好,月入2... 随着经济的发展,新兴行业不断增多,正如雷军曾说的“站在风口上,猪都可以飞起来”,在现实生活中,抓住行...
2020年最具潜力的小本创业项... 照片书就是一个把照片做成书的项目,整个微商界并没有一款像照片书这样老小皆宜的个性化定制产物,所以才显...
2018年有特色的小本投资创业... 3、拼图小店针对时下很多人追求既有个性又能带来情味的休闲方式,可开一家既能让消费者怡情消遣,又可以装...