02-动态数组 Array

学习资源:慕课网liyubobobo老师的《玩儿转数据结构》


1、简介

  • 把数据码成一排进行存放
image-20200604124110059
  • 存储的数据类型相同
  • 每一个数据在数组中对应一个索引,索引从0开始;索引可以有语意,也可以没有语意
  • 数组初始化后大小就固定了;添加、删除元素都受限

1.1、静态数组初始化

//方式一
int[] arr1 = new int[10];
//方式二
int[] arr2 = new int[]{0,1,2,3};
//方式三
int arr3 = {0,1,2,3,4,5,6,7,8,9}

1.2、数组的遍历(迭代)

for(int i = 0; i< arr.length; i++){
    arr[i]
}
        
for(数据类型 temp : arr){
    temp
}

1.3、数组元素的的修改

arr[i] = newValue

1.4、数组最大的优点

  • 存储有序,可遍历,方便快速查询
  • 数组最好应用于“索引有语意"的情况
  • 支持随机访问

2、动态数组(抽象)接口

public interface Array<E> {
    
    void insert(int index, E element);
    void remove(int index);
    void set(int index);
    void get(int index);
}

3、动态数组的实现

3.1、实现原理

  • 内部封装一个静态数组
  • 对外提供增删改查等,静态数组所没有的方法

3.2、使用泛型

  • 让我们的数据结构可以放置“任何”数据类型

  • 泛型不可以是基本数据类型,只能是类对象

    boolean,byte , char , short,int , long , float , double

  • 每个基本数据类型都有对应的包装类

    Boolean,Int,Float,Double,Byte,Char,Short,Long ,

  • 如果类为泛型类,但是在创建对象时,可以不使用泛型这个选项。

Java中创建泛型数组

//不支持
T[] array = new T[n];
//必须写为
T[] array = (T[])new Object[n];

3.3、动态化

  • 添加元素时满足某一条件,自动扩容

  • 删除元素时满足某一条件,自动缩容

3.4、代码

public class Array<E> {

    private E[] data;
    private int size;

    //有参构造器
    public Array(int capacity) {

        data = (E[]) new Object[capacity];
        size = 0;
    }

    //无参构造器
    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 isFull() {
        return getSize() == getCapacity();
    }

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

    //判断是否包含某元素
    public boolean ifContains(E element) {
        for (int i = 0; i < size; i++) {
            if (data[i].equals(element)) {
                return true;
            }
        }
        return false;
    }

    //获取某元素的索引,只能找到第一个
    public int getIndex(E element) {
        for (int i = 0; i < size; i++) {
            if (data[i].equals(element)) {
                return i;
            }
        }
        return -1;
    }

    //扩容操作,内部执行
    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 void insertToHead(E element) {
        insert(0, element);
    }

    //尾部插入一个元素
    public void insertToLast(E element) {
        insert(size, element);
    }

    //插入一个元素,插入位置:数组头、尾、元素之间
    public void insert(int index, E element) {

        if (index < 0 || index > size) {
            throw new IllegalArgumentException("插入索引不正确");
        }

        //数组扩容
        if (isFull()) {
            resize(2 * getCapacity());
        }

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

    //删除头
    public E removeHead() {
        return remove(0);
    }

    //删除头
    public E removeLast() {
        return remove(size - 1);
    }

    //指定下标删除一个元素,并返回该元素
    public E remove(int index) {

        if (index < 0 || index >= size) {
            throw new IllegalArgumentException("删除失败,索引超出数组合法界限");
        }
        E result = data[index];
        for (int i = index; i < size - 1; i++) {
            data[i] = data[i + 1];
        }
        size--;
        data[size] = null;//手动删除引用
        if (size == getCapacity() / 4 && data.length / 2 != 0) {
            resize(getCapacity() / 2);
        }
        return result;
    }

    //删除指定元素,只能删除第一个
    public boolean removeElement(E element) {

        int index = getIndex(element);
        if (getIndex(element) != -1) {
            remove(index);
            return true;
        }
        return false;
    }

    //修改一个元素
    public void set(int index, E newValue) {
        if (index < 0 || index >= size) {
            throw new IllegalArgumentException("修改失败,索引超出数组合法界限");
        }
        data[index] = newValue;
    }

    //获取一个元素,空着的位置不可以获取值
    public E get(int index) {

        if (index < 0 || index >= size) {
            throw new IllegalArgumentException("获取失败,索引超出数组合法界限");
        }
        return data[index];
    }

    //获取头元素
    public E getHead() {
        return get(0);
    }

    //获取尾元素
    public E getLast() {
        return get(size - 1);
    }

    @Override
    public String toString() {
        StringBuilder builder = new StringBuilder();
        builder.append(String.format("Array:size=%d, capacity=%d
", size, data.length));
        builder.append("[");
        for (int i = 0; i < size; i++) {
            builder.append(data[i]);
            if (i != size - 1) {
                builder.append(", ");
            }
        }
        builder.append("]");
        return builder.toString();
    }


    //交换两个索引处的值
    public void swap(int i, int j) {

        if (i < 0 || i >= size || j < 0 || j >= size)
            throw new IllegalArgumentException("索引越界");

        E e = data[i];
        data[i] = data[j];
        data[j] = e;
    }
}

3.5、测试

public class Test {

    public static void main(String[] args) {

        Array<Integer> intArray = new Array<>();

        System.out.println("是不是空数组"+intArray.isEmpty());

        intArray.addToHead(10);
        intArray.addToHead(20);
        intArray.addToLast(15);
        intArray.add(1, 39);

        System.out.println("是不是空数组"+intArray.isEmpty());
        System.out.println("是否包含15:"+intArray.ifContains(15));

        System.out.println(intArray.getSize());
        System.out.println(intArray.getCapacity());

        System.out.println(intArray);
        System.out.println("最后一个整数是:"+intArray.getLast());
        System.out.println("第一个整数是:"+intArray.getHead());
        System.out.println("索引为2的整数是"+intArray.get(2));

        intArray.removeLast();
        intArray.removeHead();
        intArray.remove(1);
        System.out.println(intArray);

        System.out.println("是否包含15:"+intArray.ifContains(15));
    }
}

4、Java中的动态数组

java.util.ArrayList

public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{
    
}

API接口

image-20200605084228121
原文地址:https://www.cnblogs.com/sout-ch233/p/13048812.html