数据结构(基于java语言描述)--动态数组

话不多说,让我们先上代码

注:构建数组所存储的元素可能为String、Integer等不同的类型,所以我们有必要设置一个泛型,让数组可以容纳我们调用时所规定的数据类型。

public class Array<E>{

    private E[] data;

    private int size;

    //有参构造函数,传入数组的容量为capacity
    public Array(int capacity) {

        data = (E[])new Object[capacity];    //类型转化
        size = 0;

    }

    //无参构造函数,默认数组容量为10
    public Array() { this(10); }



    //现在可以忽略,在之后的堆的描述中我会讲解
    public Array(E[] arr) {

        data  = (E[]) new Object[arr.length];

        for (int i = 0; i < arr.length; i++){
            data[i] = arr[i];
        }

        size = arr.length;

    }



    //获取数组的容量
    public int getCapacity() { return data.length; }


    //获取数组中元素的个数
    public int getSize() { return size; }


    //返回数组是否为空
    public boolean isEmpty() { return size == 0; }


    //index索引的位置插入新元素
    public void add(int index, E e) {

        //先对索引位置的合法性进行判断
        if ( index < 0 || index > size){
            throw new IllegalArgumentException("add failed, require index >= 0 and index <= size");
        }

        //判断数组是否需要扩容
        if (size == data.length) {
            resize( 2 * data.length);
        }

        //遍历将[indxe, size-1]的元素全部向后移动,在index位置插入新的元素
        for (int i = size - 1; i >= index; i--) {
            data[i+1] = data[i];
        }

        data[index] = e;

        //此时数组的size增加
        size++;

    }


    //向所有元素后添加一个新元素
    public void addLast(E e) {add(size, e);}


    //在所有元素前添加一个元素
    public void addFirst(E e) {add(0, e); }


    //从数组中删除index位置的元素
    public E remove(int index){

        //首先判断删除index是否合理
        if (index < 0 || index >= size){
            throw new IllegalArgumentException("remove failed. index is illegal");
        }

        E ret = data[index];

        //遍历循环,将[index+1, size-1]范围的元素向前移动一位
        for (int i = 0; i < index + 1; i++){
            data[i-1] = data[i];
        }

        //数组元素减少
        size--;

        //检查此时数组是否需要缩容
        if (size == data.length / 4 && data.length / 2 != 0){
            resize(data.length / 2);
        }
        return ret;
    }


    //删除数组中第一个元素,并返回该元素
    public E removeFirst(){ return remove(0);}


    //删除数组中最后一个元素,并返回该元素
    public E removeLast(){ return remove(size-1);}


    //修改index索引位置的元素为e
    public void set(int index, E e){
        if (index < 0 || index >= size){
            throw new IllegalArgumentException("set failed. index is illegal.");
        }
        data[index] = e;
    }


    //获取index索引的位置
    public E get(int index){
        if (index < 0 || index >= size){
            throw new IllegalArgumentException("set failed. index is illegal.");
        }
        return data[index];
    }


    //查找数组中是否有元素
    public boolean contains(E e){

        for (int i = 0; i < size; i++){
            if (data[i].equals(e)){
                return true;
            }
        }
        return false;
    }


    //查找数组中元素e所在的索引,如果不存在元素e,则返回-1    public int find(E e) {
        for (int i = 0; i < size; i++) {
            if (data[i].equals(i)) {
                return i;
            }
        }
        return -1;
    }


    //从数组中删除元素e    public void removeElement(E e){
        int index = find(e);
        if (index != -1){
            remove(index);
        }
    }


    //将数组中的两个指定元素交换
    public void swap(int i, int j){
        if (i < 0 || i>= size || j < 0 || j >= size){
            throw new IllegalArgumentException("swap failed. index is illegal.");
        }
        E ret = data[i];
        data[i] = data[j];
        data[j] = ret;
    }


    //将数组空间容量跟新
    private void resize(int newCapacity){
        E[] newData = (E[])new Object[newCapacity];

        for (int i = 0; i < size; i++){
            newData[i] = data[i];
        }

        data = newData;

    }

}

动态数组扩容的问题

上述代码中我们我们给出了如下假设:

    在给data数组添加元素前,如果data数组中的容量和元素个数size相同,扩容为原来的2倍:

    再给data数组删除元素后,如果data数组的size是capacity的1/4,并且capacity不能被2整除


如果我们单纯的将data数组中capacity和size相同时扩容(2倍),小于1/2时缩容(1/2),就会出现这样一个情况:

    当size达到capacity的零界点时,数组扩容到原来的两倍,绕后如果下一个操作是一个删除操作,数组又会瞬间进行缩容,这样反复操作会增加增删操作的时间复杂度,因此我们需要设置一个范围,来给其缓冲。


此时我们数组的复杂度:

add方 : O(n/2)

addLast: O(1)

addFirst: O(n)

remove: (n/2)

removeLast: O(1);

removeFirst: O(n)

猜你喜欢

转载自blog.csdn.net/qq_29199175/article/details/80657132
今日推荐