所谓数组,是有序的元素序列。也就是把数据码成一排存放的一种结构。
快速查询,根据索引可以快速查找相应的元素
一个数组应该具备的功能(并不固定,还可以扩充一些功能)
/** * 动态数组--泛型使其支持任意类型的数据 * @param <E> */ public class Array<E> { private E[] data; private int size;//数组中元素的个数 //构造函数--创建一个指定容量的数组 public Array(int capacity) { data = (E[]) new Object[capacity]; size = 0; } //无参构造--默认创建一个容量为10的数组 public Array() { this(10); } //获取数组中元素的个数 public int getSize() { return size; } //获取数组的容量 public int getCapacity() { return data.length; } //判断数组是否为空 public boolean isEmpty() { return size == 0; } //在数组尾部添加元素 public void addLast(E e) { add(size, e); } //在数组首部添加元素 public void addFirst(E e) { add(0, e); } //在指定位置添加元素 public void add(int index, E e) { if (size == data.length) resize(2 * data.length); //扩容2倍大小--思路就是把原来数组中的数据放到一个新的数组中 if (index < 0 || index > size) throw new IllegalArgumentException("add fail, Required index >=0 && index <=size"); for (int i = size - 1; i >= index; i--) data[i + 1] = data[i]; data[index] = e; size++; } //查询数组某个位置的元素 public E get(int index) { if (index < 0 || index > size) throw new IllegalArgumentException("get fail, index is illegal"); return data[index]; } //设置数组某个位置的元素 public void set(int index, E e) { if (index < 0 || index >= size) throw new IllegalArgumentException("set fail, index is illegal"); data[index] = e; } //查询数组中是否存在元素e public boolean contains(E e) { for (int i = 0; i < size; i++) { if (data[i] == e) return true; } return false; } //查询数组中是否存在元素e 存在则返回第一个索引 public int find(E e) { for (int i = 0; i < size; i++) { if (data[i].equals(e)) return i; } return -1; } //查询数组中是否存在元素e 存在则返回全部索引 public int findAll(E e) { return -1; } //删除数组中index位置的元素并返回 public E remove(int index) { if (index < 0 || index >= size) throw new IllegalArgumentException("remove fail, index is illegal"); E ret = data[index]; for (int i = index + 1; i < size; i++) data[i - 1] = data[i]; size--; data[size] = null;//使用泛型后 数组中size位置存放的是类对象的引用 手动释放空间 if (size == data.length / 4 && data.length / 2 !=0) //防止复杂度震荡--以及数组长度为1的情况--在数组满的情况添加元素后又删除元素 resize(data.length / 2); //缩容 return ret; } //删除数组中第一个元素 public E removeFirst() { return remove(0); } //删除数组中最后一个元素 public E removeLast() { return remove(size - 1); } //数组中如果存在一个元素,则进行删除一个 public void removeElement(E e) { int index = find(e); if (index != -1) remove(index); } //数组中如果存在元素,则进行全部删除 public void removeAllElement(E e) { int index; do { index = find(e); if (index != -1) remove(index); } while (index != -1); } //重写toString方法 @Override public String toString() { StringBuilder res = new StringBuilder(); res.append(String.format("Array: size = %d , capacity = %d\n", size, data.length)); res.append(‘[‘); //数组中没存放数组的地方不输出 for (int i = 0; i < size; i++) { res.append(data[i]); if (i != size - 1) res.append(‘,‘); } res.append(‘]‘); return res.toString(); } //数组长度动态变化 private void resize(int newCapacity) { E[] newData = (E[]) new Object[newCapacity]; for (int i = 0; i < size; i++) newData[i] = data[i]; data = newData; } }
什么是时间复杂度这里看另外一篇文章https://blog.csdn.net/qq_41523096/article/details/82142747
假设数组容量是8,使用addLast()方法需要9次操作才触发一次resize(转移8个元素到新数组),一共17次操作,相当于平均每次addLast,进行2次操作,所以均摊计算它的复杂度是O(1);
同理removeLast也是O(1); 同时考虑这两个方法,特殊情况当添加一个元素触发了扩容,然后有删除这个元素触发缩容,造成复杂度震荡.解决方法Lazy 也就是缩容的时候不用那么急
原文:https://www.cnblogs.com/phperpxy/p/10263698.html