数据结构之一数组

75 阅读5分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第17天,点击查看活动详情

数组

image.png

  • 将数组码成一排进行存放

封装我们自己的数组

public class Array {
​
    private int[] data;
    //在data中有多少个有效的元素
    private int size;
​
    //构造函数,copacity是用户传入的容量大小,通过传入的copacity构造Array
    public Array(int copacity) {
​
        data = new int[copacity];
        size = 0;
    }
    //如果他不知道自己声明的数组需要装多少元素,我们可以让他不用指定
    public Array() {
        this(10);
    }
​
    //获取数组有多少个元素
    public int getSize() {
        return size;
    }
    //获取数组的容量大小
    public  int getCopacity() {
        return data.length;
    }
    //返回数组是否为空
    public boolean isEmpty() {
        return size == 0;
    }
​

向数组中添加元素

向数组的末尾添加元素,记得维护数组的size

 //向数组末尾添加元素
    public void addList(int e) {
//        我们要对传入的进行一个判断,是否超过我们数组的长度
        if (size == data.length) {
            throw new IllegalArgumentException("Array is full");
        }
        data[size] = e;
        size++;
        上面两句相当于下面这一句
        //data[size++] = e;
    }

向指定位置插入元素

数组的索引是从零开始,所以size的指向是下一个空的元素

思路:从最后一个元素(size-1)开始挪动,等露出我们想插入的地方,我们就把元素插入,然后维护数组长度

public void add(int index, int e) {
        if (size == data.length) {
            throw new IllegalArgumentException("Array is full");
        }
//        我们要对用户传入的index判断是否合法
        if (index < 0 || index > size) {
            throw new IllegalArgumentException("index < 0 || index > size");
        }
    
          for (int i = size -1; i >= index; i--) {
            data[i + 1] = data[i];
        }
            data[index] = e;
            size ++;
​
    
    
 //由于我们写了add方法,那我们上面的数组末尾插入可以修改一下
      public void addList(int e) {
        add(size, e);
    }
        
    //  同理,我们复用一下add方法实现 数组的头部插入元素
    public  void addFirst(int e) {
        add(0,e);
    }
​
       

查询元素和修改元素

数据是被我们封装在data中的,对于静态数组,我们可以使用传入索引的办法去查找,在我们自定义当中也是可以使用的,对于每一个类都要覆盖父类的一个方法

​
    //查询
    @Override
    public String toString() {
        //拼接一个字符串
        StringBuilder res = new StringBuilder();
//        首先String.format初始化,反应我们数组的基本信息
        res.append(String.format("Array:size = %d, copacity = %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();
​
    }
//    获取指定索引index元素
    int get(int index) {
        if(index < 0 || index > size)
            throw new IllegalArgumentException("get is fail.");
        return data[index];
    }
​
    //    修改index索引的元素
    int set(int index,int e) {
        if(index < 0 || index > size)
            throw new IllegalArgumentException("set is fail.");
        return data[index] = e;
​
    }
​

数组的包含,搜索和删除

一些情况下,数组中有很多元素,我们要查询是否包含了某个元素

//    查询数组中是否含有我们传入的元素
    public boolean contains(int e) {
        for (int i = 0; i < size; i++) {
            if (data[i] == e) {
                return true;
            }
        }
        return false;
    }
//查找指定元素和索引的位置,如果不存在,返回-1
    public int find(int e) {
        for (int i = 0; i < size; i++) {
            if (data[i] == e) {
//                返回索引
                return i;
            }
        }
        return -1;
​
    }

删除指定元素

原理:需要删除的地方,将他的下一个值覆盖掉他的值,后面的依次覆盖前面的值,维护数组的size

//    从数组中删除指定元素,返回删除的元素
    public int remove(int index) {
        if(index < 0 || index > size){
            throw new IllegalArgumentException("get is fail.");}
//        将要被删除的元素存储起来,将来返回给用户
        int res =  data[index];
        for (int i = index + 1; i < size; i++) {
            data[i - 1] = data[i];
        }
        size--;
        return res;
    }
​
//    删除第一个元素
    public int removeFrist(int index) {
        return remove(0);
    }
    //    删除最后一个元素
    public int removeLast(int index) {
        return remove(size - 1);
    }
//    查看数组中是否有这个元素,并将它删除
​
    public  boolean removeElement(int e) {
        int index = find(e);
        if (index != -1) {
            remove(index);
            return true;
        }
        return false;
​
    }
​

使用泛型

由于我们目前写的只有int类型,我们需要存放任意类型,才能更加实用

  • 让数据结构可以放置“任意类型”的数据
  • 不可以是基本数据类型,只能是类对象
​
public class Arraytest<E> {
​
    private E[] data;
    //在data中有多少个有效的元素
    private int size;
​
    //构造函数,copacity是用户传入的容量大小,通过传入的copacity构造Array
    public Arraytest(int copacity) {
​
        data = (E[])new Object[copacity];
        size = 0;
    }
    //如果他不知道自己声明的数组需要装多少元素,我们可以让他不用指定
    public Arraytest() {
        this(10);
    }
​
    //获取数组有多少个元素
    public int getSize() {
        return size;
    }
    //获取数组的容量大小
    public  int getCopacity() {
        return data.length;
    }
    //返回数组是否为空
    public boolean isEmpty() {
        return size == 0;
    }
​
    //向数组末尾添加元素
    public void addLast(E e) {
////        我们要对传入的进行一个判断,是否超过我们数组的长度
//        if (size == data.length) {
//            throw new IllegalArgumentException("Array is full");
//        }
//        data[size] = e;
//        size++;
​
        add(size, e);
    }
    //    数组的头部插入元素
    public  void addFirst(E e) {
​
        add(0, e);
    }
​
    //在index的位置插入一个元素e
    public void add(int index, E e) {
        if (size == data.length) {
            throw new IllegalArgumentException("Array is full");
        }
//        我们要对用户传入的index判断是否合法
        if(index < 0 || index > size)
            throw new IllegalArgumentException("Add failed. Require index >= 0 and index <= size.");
​
        for (int i = size -1; i >= index; i--) {
            data[i + 1] = data[i];
        }
            data[index] = e;
            size ++;
​
​
    }
​
//    获取指定索引index元素
    E get(int index) {
        if(index < 0 || index > size)
            throw new IllegalArgumentException("get is fail.");
        return data[index];
    }
​
    //    修改index索引的元素
    E set(int index,E e) {
        if(index < 0 || index > size)
            throw new IllegalArgumentException("set is fail.");
        return data[index] = e;
​
    }
    //查询
    @Override
    public String toString() {
        //拼接一个字符串
        StringBuilder res = new StringBuilder();
//        首先String.format初始化,反应我们数组的基本信息
        res.append(String.format("Array:size = %d, copacity = %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();
​
    }
​
//    查询数组中是否含有我们传入的元素
    public boolean contains(E e) {
        for (int i = 0; i < size; i++) {
            if (data[i] .equals(e) ) {
                return true;
            }
        }
        return false;
    }
//查找指定元素和索引的位置,如果不存在,返回-1
    public int find(E e) {
        for (int i = 0; i < size; i++) {
            if (data[i].equals(e)) {
//                返回索引
                return i;
            }
        }
        return -1;
​
    }
​
//    从数组中删除指定元素,返回删除的元素
    public E remove(int index) {
        if(index < 0 || index > size){
            throw new IllegalArgumentException("get is fail.");}
//        将要被删除的元素存储起来,将来返回给用户
        E res =  data[index];
        for (int i = index + 1; i < size; i++) {
            data[i - 1] = data[i];
        }
        size--;
        //  删除size指向的引用。java回收机制就能删除对象的引用
        // 当我们使用泛型时,数组中存储的时一个一个的引用。当数组中还存在着一个对象的引用的话,就不会被java自动回收机制所回收
        data[size] = null;
        return res;
    }
​
//    删除第一个元素
    public E removeFrist(int index) {
        return remove(0);
    }
    //    删除最后一个元素
    public E removeLast(int index) {
        return remove(size - 1);
    }
//    查看数组中是否有这个元素,并将它删除
​
    public  boolean removeElement(E e) {
        int index = find(e);
        if (index != -1) {
            remove(index);
            return true;
        }
        return false;
​
    }
}
​

动态数组

思路:如果原来的数组满了,我们开辟一个更大的空间,将原来的数组放到我们这个大数组当中

  private void resize(int newCapacity) {
      强转
       E[] newData = (E[])new Object[newCapacity];
        for (int i = 0; i < size; i++) {
            旧数组进入新数组
            newData[i] = data[i];
        }
      改变指向
        data = newData;
    }