数据结构之数组

144 阅读2分钟

什么是数据结构

image.png image.png

二次封装java中的数组

  • 索引没有语意,如何表示没有元素。
  • 如何添加元素?如何删除元素?

数据结构实现

  • size属性的位置就是将要添加元素的位置
public class Array<E> {
//    设置一个int类型的数组
    private E[] arr;
    private int size;

    public Array(int capacity) {
//        arr = new int[capacity];
        arr = (E[]) new Object[capacity];
    }

    public Array() {
        this(10);
    }

//    获取元素实际个数
    public int getSize() {
        return size;
    }
//    获取数组容量
    public int getCapacity() {
        return this.arr.length;
    }
//    判断数组是否为空
    public boolean isEmpty() {
        return size == 0;
    }
//    添加元素。注意size的位置不能出现值的
    public void add(int index, E element) {
//        this.arr[index] = element;
//        size++;
//        1. 先判断填入的元素是否已满
        if(size == arr.length) {
//            throw new Error("add fail, size == arr.length");
//            扩容为原来的2倍
            resize(arr.length * 2);
        }
//        2. 判断填入的元素位置是否越界。这里我们判断越界使用size。不想要稀疏数组。
        if(index > size || index < 0) throw new Error("add fail, index > size || index < 0");
//        3. 开始插入元素,开始向后推移
        for(int i = size - 1; i >= index; i--) {
//            这里刚好利用size位置存入空值的特性。
            arr[i + 1] = arr[i];
        }
//        4. index的位置已无元素,插入元素
        arr[index] = element;
        size++;
    }
//    在最后添加元素
    public void addLast(E element) {
        add(size, element);
    }
//    在最开始添加元素
    public void addFirst(E element) {
        add(0, element);
    }
//    toString
    @Override
    public String toString() {
        StringBuilder res = new StringBuilder();
        res.append(String.format("Array capacity %d, Array size %d\n", arr.length, size));
        res.append("[");
        for(int i = 0; i < size; i++) {
            res.append(arr[i]);
            if(i != size - 1) {
                res.append(",");
            }
        }
        res.append("]");
        return res.toString();
    }
//    获取元素
    public E get(int index) {
        if(index < 0 || index >= size) throw new Error("get fail, index < 0 || index >= size");
        return arr[index];
    }
//    修改元素
    public void set(int index, E element) {
        if(index < 0 || index >= size) throw new Error("get fail, index < 0 || index >= size");
        arr[index] = element;
    }
//    判断是否包含元素
    public boolean contains(E element) {
        for(int i = 0; i < size; i++) {
            if(element == arr[i]) {
                return true;
            }
        }
        return false;
    }
//    查找元素下表
    public int find(E element) {
        for(int i = 0; i < size; i++) {
            if(element == arr[i]) {
                return i;
            }
        }
        return -1;
    }
//    删除元素
    public boolean remove(int index) {
        if(index < 0 || index >= size) {
            throw new Error("delete fail, index < 0 || index >= size");
        }
        for(int i = index; i < size; i++) {
            arr[i] = arr[i + 1];
        }

        size--;
        // 这里为了防止扩容震荡,所以size 等于容积的1/4时,在缩容
        if(size == arr.length / 4 && data.length / 2 != 0) {
//            缩容为原来的一半。
            resize(arr.length / 2);
        }
        return true;
    }
//    删除最后一个元素
    public boolean removeLast() {
        return remove(size - 1);
    }
//    删除第一个元素
    public boolean removeFirst() {
        return remove(0);
    }
//    扩容
    public void resize(int capacity) {
//        1. 先遍历原数组,并取出元素。
        E[] newArr = (E[]) new Object[capacity];
        for(int i = 0; i < size; i++) {
            newArr[i] = arr[i];
        }
        arr = newArr;
        newArr = null;
    }
}

数据结构复杂度分析

基本方法

image.png

image.png

image.png

image.png

扩容方法

image.png image.png image.png image.png image.png

这里会引起不断地扩容和降容。出现复杂度震荡。所以我们可以改变降容的条件。不让其size = arr.length / 2 时就开始降容。而是size = arr.length / 4。

image.png