简单学习了数据结构基础,创建动态数组,将原有的静态数组,改变为动态数组。
接下来对动态数组的创建思路进行解释
构建俩个构造函数,可以指定capacity的大小来创建数组容量,若不传入参数,则默认容量为10
private E[ ] data;
private int size;
//构造函数,传入数组的容量capacity构造Array
public Array(int capacity) {
data =(E[]) new Object [capacity];
size =0;
}
//无参数的构造函数,默认数组的容量capacity=10
public Array() {
this(10);
}
getsize方法返回数组的元素个数
//获取数组中的元素个数
public int getsize() {
return size;
}
getcapactiy方法返回数组的容量
//获取数组的容量
public int getcapacity() {
return data.length;
}
isEmpty方法判断数组是否为空
//返回数组是否为空
public boolean isEmpty() {
return size==0;
}
find方法寻找元素e的索引,若e不存在则返回-1
public int find (E e) {
for(int i=0;i<size;i++) {
if(e==data[i]) {
return i;
}
}
return -1;
}
contains方法 查找数组中是否存在元素e
public boolean contains (E e) {
for(int i=0;i<size;i++) {
if( data[i].equals(e)) {
return true;
}
}
return false;
}
get方法获取index索引位置的元素
if函数判断传入的参数是否合理
public E get(int index) {
if(index<0||index >size) {
throw new IllegalArgumentException("Get failed.index is illegal");
}
return data[index];
}
set方法修改index索引位置的元素e
void set(int index,E e) {
if(index<0||index >size) {
throw new IllegalArgumentException("Set failed.index is illegal");
}
data[index] =e;
}
以上方法为数组的基本常用方法,但无法做到动态数组。
以下方法将静态数组变为动态数组。
resize方法将数组变为可伸缩性
创建一个新的newData数组,将data数组的值赋值到newData数组中,最后将newData数组赋值给data数组,从而达到数组伸缩。
private void resize(int newCapacity) {
E[] newData= (E[])new Object [newCapacity];
for(int i=0;i<size;i++) {
newData[i] = data [i];
}
data=newData;
}
add方法在第index个位置插入一个新元素e
其中第一个if函数会判断传入的int参数是否正确,若不正确将抛出异常。
第二个if函数判断数组是否空余,若数组中的元素个数等于数组的容量,将数组扩容为原数组的二倍。
这里强调一下为什么要扩容为原来的二倍,而不是加一个常数。因为如果加一个常数,无法确定所加常数的大小。例如:所加常数大小为10,如果数组的原有长度为1000,将数组扩容之后数组的长度变为1010,扩容的10长度就会显得微不足道,可能会频繁调用resize方法,使代码的利用率不高。如果所加长度为1000,若原有长度为10,扩容之后将浪费很大一部分的内存,使代码的利用率不高。所以综上所述,将数组扩容为原来的2倍,最为合理。(当然也可以扩容为原来的x倍)
//在第index个位置插入一个新元素
public void add(int index,E e) {
if(index<0||index >size) {
throw new IllegalArgumentException("Add failed.Require index >=0 and index<=size.");
}
if(size==data.length) {
resize(2*data.length);
}
for(int i=size-1;i>=index;i--) {
data[i+1] = data[i];
}
data[index]=e;
size++;
}
remove方法从数组中删除index索引位置的元素,返回删除的元素
这里解释一下第二个if函数为什么当size==data.length/4时,将数组变为原来的1/2。
如果是size==data.length/2时,可能会频繁调用扩容方法。例如:原数组的容量为5,当加入第6个元素时,将会进行数组的扩容,数组容量变为原来的2倍。当扩容之后,删除第6个元素,会立马将数组容量变为1/2,当频繁进行添加删除操作,会频繁调用resize方法,使代码利用率降低。当size==data.length/4时,将数组变为原来的1/2,数组有1/2的长度为空,进行添加操作时,不会立马调用resize方法,从而使代码效率提高。
public E remove(int index) {
if(index<0||index >size) {
throw new IllegalArgumentException("Remove failed.index is illegal");
}
E ret =data[index];
for(int i=index+1;i<size;i++) {
data[i-1]=data[i];
}
size--;
data[size]=null;
if(size==data.length/4&&data.length/2!=0) {
resize(data.length/2);
}
return ret;
}
最后将重写toString方法
public String toString() {
StringBuilder res =new StringBuilder();
res.append(String.format("Array: size=%d,capacity =%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();
}