zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    LinkedList实现原理(JDK1.8)
    ArrayList实现原理(JDK1.8)
    java集合讲解
    MySQL系列:MySQL的基本使用
    MySQL系列:一句SQL,MySQL是怎么工作的?
    MySQL系列:走进数据库,相关概念你都明白吗?
    MySQL系列:Windows 下 MySQL 8.X 的安装
    SpringBoot系列:Spring Boot集成定时任务Quartz
    SpringBoot系列:Spring Boot定时任务Spring Schedule
    SpringBoot系列:Spring Boot异步调用@Async
  • 原文地址:https://www.cnblogs.com/sout-ch233/p/13048812.html
Copyright © 2011-2022 走看看