【玩转数据结构 从入门到进阶1学习笔记】数组

封装属于自己的数组

封装一个属于自己的数组,可以进行增删改查等操作,还可以不同的数据类型,以自己的格式输出。
下面是数组里的方法一览
在这里插入图片描述

add方法

想要在指定位置添加一个元素,那么这个位置后面的元素必须全部向后移一位,我们可以从最后一个元素开始遍历,每个元素向后移一位,移完后则指定位置空余出来,再将元素添加进去,在此之前,我们还要判断元素是否已经填满数组,还要输入的指定值是否小于0或者大于元素个数,完成这个方法后,我们可以在首尾添加元素时将此方法复用

 public void add(int index,E e){
        if (size==data.length){
            throw new IllegalArgumentException("Array  add is failed");
        }
        if (index<0 ||index>size){
            throw new IllegalArgumentException("Array add id failed");
        }

        for (int i=size-1;i>=index;i--){
            data[i+1]=data[i];
        }
        data[index]=e;
        size++;
    }

    public void addLast(E e){
        add(size,e);
    }

    public void addFirst(E e){
        add(0,e);
    }

在此之前,我们可以重写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<data.length;i++){
            res.append(data[i]);
            if (i!=size-1){
                res.append(",");
            }
        }
        res.append("]");
        return res.toString();
    }

根据索引位置获取元素和更改元素

  public E get(int index){
        return data[index];
    }

    public  void set(int index,E e){
        data[index]=e;
    }

remove方法

同理,删除一个元素也要判断输入索引位置是否小于0或者大于大于元素个数,这里删除则是从index位置开始,后面元素覆盖当前元素值,并返回一个索引值

public E remove(int index){
        if (index<0 ||index>=size){
            throw new IllegalArgumentException("Array remove is failed");
        }
        E ret=data[index];
        for (int i=index+1;i<size;i++){
            data[i-1]=data[i];
        }
        size--;
        data[size]=null;
        
        return ret;
    }

这里也可以复用remove方法,并且用于removeFirst和removeLast

    public E removeLast(){
        return remove(size);
    }

    public E removeElement(E e){
        int index=find(e);
        return remove(index);
    }

动态数组

这里我们可以自己设计一个动态数组,用一个resize方法,而扩容的容量选择为原来数组的两倍,ArrayList选择的是1.5倍,这个resize方法,是将原来数组的内容复制到新的扩容数组里面,以此替代原来数组,达到扩容目的

/*
    动态数组,扩容,将原来的数组内容复制到一个已扩容的数组里面,再指向该数组,即完成数组扩容
    resize方法虽然复杂度较大,但是均摊复杂度后,依然不失为一种提高性能的方法
     */
    public  void resize(int newcapacity){
        E[] newData=(E[])new Object[newcapacity];
        for (int i=0;i<size;i++){
            newData[i]=data[i];
        }
        data=newData;
    }

数组既然可以扩容,我们也可以缩小容量,可以在remove方法里调用,做个判断,当数组元素个数变为数组容量的1/4时,我们调用resize方法,我们不选择在1/2数组容量时调用是因为有个复杂度振荡问题,比如原来数组容量为10,我们在后面加一个元素后数组容量扩容为20,此时时间复杂度又耗费O(n),当我们又删除一个元素时,如果是1/2容量时缩小,则又耗费O(n)时间复杂度,所以循环以往,就会造成复杂度振荡

源代码

public class Array <E>{

    private E [] data;
    private  int size;//元素个数

    //带参构造函数,初始化数组容量为capacity
    public Array(int capacity){
        data=(E[])new Object[capacity];
        size=0;
    }

    //无参构造函数
    public Array(){
        this(10);
    }

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

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

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

    /*
    往数组指定位置添加元素
     */
    public void add(int index,E e){
        if (size==data.length){
            resize(2*data.length);
        }
        if (index<0 ||index>size){
            throw new IllegalArgumentException("Array add id failed");
        }

        for (int i=size-1;i>=index;i--){
            data[i+1]=data[i];
        }
        data[index]=e;
        size++;
    }

    /*
    动态数组,扩容,将原来的数组内容复制到一个已扩容的数组里面,再指向该数组,即完成数组扩容
    resize方法虽然复杂度较大,但是均摊复杂度后,依然不失为一种提高性能的方法
     */
    public  void resize(int newcapacity){
        E[] newData=(E[])new Object[newcapacity];
        for (int i=0;i<size;i++){
            newData[i]=data[i];
        }
        data=newData;
    }

    public void addLast(E e){
        add(size,e);
    }

    public void addFirst(E e){
        add(0,e);
    }

    /*
    构造自己的输出格式
     */
    @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<data.length;i++){
            res.append(data[i]);
            if (i!=size-1){
                res.append(",");
            }
        }
        res.append("]");
        return res.toString();
    }

    public E get(int index){
        return data[index];
    }

    public  void set(int index,E e){
        data[index]=e;
    }

    /*
    以下是包含,搜索和删除
     */

    public  boolean contains(E e){
        for(int i=0;i<data.length;i++){
            if (data[i].equals(e)) {
                return true;
            }
        }
        return false;
    }

    //找出搜索元素的索引
    public int find(E e){
        for(int i=0;i<data.length;i++){
            if (data[i].equals(e)) {
                return i;
            }
        }
        return -1;
    }

    //删除指定位置元素
    public E remove(int index){
        if (index<0 ||index>=size){
            throw new IllegalArgumentException("Array remove is failed");
        }
        E ret=data[index];
        for (int i=index+1;i<size;i++){
            data[i-1]=data[i];
        }
        size--;
        data[size]=null;
       
        //数组缩小,这里缩小到1/4是为了防止复杂度振荡
        if (size==data.length/4&& data.length / 2 != 0){
            resize(data.length/4);
        }
        return ret;
    }

    public E removeLast(){
        return remove(size);
    }

    public E removeElement(E e){
        int index=find(e);
        return remove(index);
    }

    public void removeAllElement(E e){
        for(int i=0;i<size;i++){
            if (data[i]==e) {
                remove(i);
            }
        }
    }

    /*
    使用泛型,可以让数组承载任意类型,包括用户自定义的类,但只能是类对象,像基本数据类型不可以
    得用它们的包装类,如Boolean,Byte,Char,Short,Long,String,Integer,Double
     */




}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱技术的小小林

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值