本文为学习《漫画算法》中数组部分的笔记,涉及到数组的插入,删除与扩容,以及回顾了Java中构造方法与this的一些基础知识。涵盖的内容较多就不一一例举出来了,能够理解每一行代码的作用就差不多了。

目录

各操作的代码实现

时间复杂度与空间复杂度分析

数组的优势和劣势分析


首先罗列几个知识点:

  1. 数组存放在一块连续的地址空间,不能跳过某个存储单元进行存储->数组初始化时,必须指定数组的大小,或者指定数组的初始值(这一点与C+++中的vector向量不同,它可以根据需要自动调整自身大小)
  2. 数组越界:数组下标超过(大于等于)数组长度范围
  3. 数组扩容:定义一个数组长度等于原数组长度两倍的数组,然后使用数组拷贝方法(System.arraycopy(oldarray, 0, newarray, 0, oldarray.length)),将原数组中的元素全部拷贝到新数组,最后将新数组赋值给原数组。

各操作的代码实现

数组插入部分代码为:insert(int element, int index),数组删除元素:delete(int index),数组扩容:resize()

public class MyArray {
    private int[] array;
    private int size;//用size来表示数组中的元素个数
    private static int age;//age变量在下面没用到,只是在这里举例说明static修饰的静态变量是属于类的,在类加载的时候一起加载到内存中

    /*
    构造方法的特点:
    1.方法名和类名相同
    2.方法名前面没有返回值类型声明(方法中不能使用return语句)
     */
    public MyArray(){
        System.out.println("调用无参构造方法");
    }

    /*
    A.构造方法的重载:
    构造方法的参数类型与参数个数不同即可构成重载

    B.构造方法之间可以相互调用:
    1.在构造方法中,通过this调用其他构造方法,只能出现在第一行,且只能出现一次;
    2.不能在一个类的两个构造方法中使用this相互调用
     */
    public MyArray(int capacity){
        this();
        this.array = new int[capacity];//int[] array = new int[capacity];
        size = 0;//(此句可省略,默认的整型初始值为0)若在变量前使用this可以明确访问一个类的成员变量,解决与局部变量的冲突->成员变量与局部变量重名时采用“就近原则”
    }

    public void insert(int element, int index) throws Exception{//插入元素时可能会出现异常,我们需要在调用位置用try/catch捕获一下或者在方法后使用throws Exception抛出
        //判断访问下标是否超出范围
        if(index < 0 || index > size || index >= array.length){//当index=size的时候插入在数组尾部
            throw new IndexOutOfBoundsException("超出数组实际元素范围");
        }

        //数组扩容
        if(size >= array.length)
            resize();

        //在插入之前,先判断插入的位置index是否大于最后一个元素的位置size-1
        //若插入位置小于等于最后一个元素所在位置,则从右向左循环,将元素逐个向右挪一位
        for(int i = size-1; i>=index; i--){
            if(i+1 >= array.length)
                throw new IndexOutOfBoundsException("数组越界,需要扩容");
            array[i+1] = array[i];
        }

        //腾出的位置放入新元素,元素个数加1
        array[index] = element;
        size++;
    }

    public int delete(int index) throws Exception{
        if(index < 0 || index >= size){
            throw new IndexOutOfBoundsException("超出数组实际元素范围!");
        }
        int tem = array[index-1];
        int i;
        for(i = index-1 ; i < size-1; i++){
            array[i] = array[i+1];
        }
        array[i]=0;//跳出循环时i=size-1,此时需要将其置为0
        //array[size-1]=0;
        size--;
        return tem;

    }

    public void resize(){
        int[] newArray = new int[array.length*2];
        System.arraycopy(array, 0, newArray, 0, array.length);
        array = newArray;
    }

    public void output(){
        for(int i = 0; i < array.length; i++){
            System.out.print(array[i]+" ");
        }
    }

    public static void input(){
        System.out.println("input");
        //size++;提示错误,静态方法不能使用非静态资源(只有在类实例化之后才能使用)
    }

    public static void main(String[] args) throws Exception{
        MyArray myArray = new MyArray(4);//整形数组初始化时默认每个元素都是0
        myArray.insert(3,0);
        myArray.insert(7,1);
        myArray.insert(9,2);
        myArray.insert(5,3);
        myArray.insert(6,1);
        myArray.delete(2);
        myArray.output();
    }
}

 程序的输出结果为:

调用无参构造方法
3 7 9 5 0 0 0 0 

注释也写的比较详细, 仅作为一个笔记,供大家参考!

时间复杂度与空间复杂度分析

插入操作,数组扩容的时间复杂度为O(n), 插入并移动元素的时间复杂度也是O(n),因此综合的插入时间复杂度为O(n)。

删除操作,只涉及到元素的移动,因此时间复杂度也是O(n)

数组的优势和劣势分析

优势在于:数组拥有非常高效的随机访问能力,只要给出下标,就能用常量时间找到对应元素;

劣势在于:在插入和删除元素的时候,由于数组元素连续紧密地存储在内存中,因此需要频繁地移动元素。

因此,数组适合读操作多,写操作少的场景。