数据结构之数组(java版)

数组是我接触的第一个数据结构知识,对于数组,在我们编码中是十分常见的一种数据结构。下面是我学习的时候写的关于数组的一些操作,数组对我我们的后期的学习我觉得是一个铺垫性的作用,所以学好数组是必须的。

public class Array<E> {
    //定义一个泛型数组
    private E [] data;
    //相当于一个指针,标记着数组的长度
    private int size;
    //初始化data的容量,但是泛型数组由于泛型擦除只能够通过Object来进行申明
    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 addFrist(E e){
        add(0,e);
    }
    //在index插入元素,对于数组来说呢,一般添加元素就是将在index位置的元素覆盖在后一个元素上面,最后size++
    //我们一般采取从后往前遍历到index的位置这样不会造成数组越界
    public void add(int index,E e){
        //扩容,当size等于数组长度时,进行扩容
        if (size == data.length){
            resize(2*data.length);
        }
        //参数校验
        if (index < 0 || index > size){
            throw  new IllegalArgumentException("索引违法");
        }
        for (int i = size-1;i >= index ; i--) {
            data[i + 1] = data[i];
        }
            data[index] = e;
            size++;
    }
    //取出最后一个元素
    public E getLast(){
        return get(size-1);
    }
    //取出第一个元素
    public E getFirst(){
        return get(0);
    }
    //获取index的元素,直接返回date【index】
    public E get(int index){
        if (index <0 || index>=size){
            throw new IllegalArgumentException("索引违法");
        }
        return data[index];
    }
    //更新index位置的元素
    void set(int index, E e){
        if (index <0 || index>=size){
            throw new IllegalArgumentException("索引违法");
        }
        data[index] = e;
    }
    //判断元素e是否存在,从前往后遍历
    public boolean contains(E e){
        for (int i = 0;i< size;i++){
            if (data[i].equals(e))
                return true;
        }
        return false;
    }
    //查找e元素所在的索引,没有返回-1
    public int find(E e){
        for (int i = 0;i< size;i++) {
            if (data[i].equals(e))
                return i;
        }
        return -1;
    }
    //删除index元素,并且返回删除元素,对于删除元素,我们首先直接将获取到index的后一个位置,
    // 将后一个位置直接覆盖然后size--并让最后的元素为null
    public E remove(int index){

        E ret =data[index];
        for (int i=index + 1;i<size;i++){
            data[i-1] =data[i];
        }
        size--;
        data[size] = null;
        //因为在扩容的时候我们是2倍,在这里为了降低复杂度的震荡,我们将缩容为四分之一
        if (size == data.length/4)
            resize(data.length/2);
        return ret;
    }
    public E removeFrist(){
       return remove(0);
    }
    public E removeLast(){
        return remove(size-1);
    }
    public void removeElement(E e){
        int index=find(e);
        if (index != -1)
            remove(index);
    }
    //为了更好地看到数组的变化重载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;
    }

    public static void main(String[] args) {
        Array<Integer> array=new Array<Integer>();
        for (int i=0;i<10;i++){
            array.addFrist(i);
        }
        System.out.println(array);
    }
}
/**
 * 对于现在的这个数组,我们已经差不多已经完成了一些常规的CURD,对于数组我觉得我想说的是
 * 数组不是那么的困难,但是对于我们后面的学习是十分重要的
 * 在java中的ArrayList的底层也是一个动态数组进行封装的,默认初始值为10,当然比我们现在封装的数组好很多
 */

对于我编写的这个数组中对于复杂度来讲,add方法的平均复杂度为O(N),find方法的复杂度为O(1),remove方法的平均复杂度为O(n),但是值得一提的是在在这里面做了一个处理复杂度的震荡的做法,在我的代码中的remove,add方法的扩容大小是不一样的因为在扩容的时候,我的初始容量为10,当addFirst执行完之后,再执行remove方法,那么两次复杂度就为0(n),这样是很麻烦的。所以我们扩容和缩容的边界值是不一样的,这样就巧妙的处理了复杂度的震荡。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值