Java数据结构-动态数组实现以及分析

今天来实现一个Java写的动态数组,就像平时使用的ArrayList一样,当容量不够时可以动态扩容,容量过大时可以动态缩容。
需要的一些方法:
有参构造Array(int capacity)capacity用来指定数组大小
无参构造Array()默认开辟10个对象大小的数组
getSize()
getCapacity()
isEmpty()判断是否为空
find(E e)查找函数
add(int index,E e)向指定位置添加元素的方法
addFirst(E e)向数组头部添加元素
addLast(E e)向数组尾部添加元素
private resize(int capacity)重新分配数组容量的方法
remove(int index)删除指定位置的元素
removeFirst()删除数组的第一个元素
removeLast()删除数组的最后一个元素
get(int index)获取指定位置的元素
contains(E e)判断数组中是否存在元素e
set(int index,E e)修改指定位置的元素
toString()

package com.yunding.dataStructures;

import java.util.Map;

/**
 * @Author: Lang
 * @Date: 2020/7/4
 * @Description: 动态数组
 */
public class Array<E> {
    private E[] data;
    private int size;

    //构造函数,传入数组的容量capacity构造Array
    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 this.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(index < 0 || index > size){
            throw new IllegalArgumentException("index<0 or index>size");
        }
        //动态扩容
        if(size == data.length){
            resize(2*data.length);
        }
        for(int i = size-1; i >= index; i--){
            data[i+1] = data[i];
        }
        data[index] = e;
        size ++;
    }

    private void resize(int capacity) {
        E[] newData = (E[]) new Object[capacity];
        for(int i=0;i<size;i++){
            newData[i] = data[i];
        }
        data = newData;
    }

    //从数组中删除index位置的元素,返回删除的元素
    public E remove(int index){
        if(index < 0 || index > size){
            throw new IllegalArgumentException("index<0 or index>size");
        }
        E ret = data[index];
        for(int i = index+1 ; i < size ; 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);
    }

    //查找指定位置的元素
    public E get(int index){
        return data[index];
    }

    //查询是否包含
    public boolean contains(E e){
        for(int i=0;i<size;i++){
            if(data[i].equals(e)){
                return true;
            }
        }
        return false;
    }

    //修改指定下标的元素,并返回修改前的元素
    public E set(int index,E e){
        if(index < 0 || index > size){
            throw new IllegalArgumentException("index<0 or index>size");
        }
        E e1 = data[index];
        data[index] = e;
        return e1;
    }

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

    @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();
    }
}

核心在于add(),remove()和resize()方法,添加方法会在容量不足时重新申请内存扩容,容量达到原来的两倍。
而删除元素当现有元素是数组容量的1/2时并不会立马缩容,因为为防止复杂度震荡,复杂度震荡是什么呢?
当一个数组原有容量为n,当数组满后继续添加元素就会扩容,当再删除一个元素,又进行缩容,再添加元素时又进行扩容,这样就会导致复杂度很高。
所以,为了防止这种情况,删除元素时可以在数组的元素为数组长度的1/4时再进行缩容,这样可以有效避免复杂度震荡。

操作firstlast一般
添加元素O(n)O(1)O(n/2)=O(n)
删除元素O(n)O(1)O(n/2)=O(n)
修改元素set(int index,E e)O(1)
查找元素get(int index)contains(E e)find(E e)
O(1)O(n)O(n)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值