本文为学习《漫画算法》中数组部分的笔记,涉及到数组的插入,删除与扩容,以及回顾了Java中构造方法与this的一些基础知识。涵盖的内容较多就不一一例举出来了,能够理解每一行代码的作用就差不多了。
目录
各操作的代码实现
时间复杂度与空间复杂度分析
数组的优势和劣势分析
首先罗列几个知识点:
- 数组存放在一块连续的地址空间,不能跳过某个存储单元进行存储->数组初始化时,必须指定数组的大小,或者指定数组的初始值(这一点与C+++中的vector向量不同,它可以根据需要自动调整自身大小)
- 数组越界:数组下标超过(大于等于)数组长度范围
- 数组扩容:定义一个数组长度等于原数组长度两倍的数组,然后使用数组拷贝方法(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)
数组的优势和劣势分析
优势在于:数组拥有非常高效的随机访问能力,只要给出下标,就能用常量时间找到对应元素;
劣势在于:在插入和删除元素的时候,由于数组元素连续紧密地存储在内存中,因此需要频繁地移动元素。
因此,数组适合读操作多,写操作少的场景。