准备工作:
/**
* 二次封装属于我们自己的数组的准备工作
*/
public class Array {
private int[] data;
private int size;
public Array(int capacity){
data=new int[capacity];
size=0;
}
//无参构造函数,默认数组的容量是10
public Array(){
this(10);
}
public int getSize(){
return size;
}
public int getCapacity(){
return data.length;
}
public boolean isEmpty(){
return size==0;
}
}
//在所有元素后添加新元素
public void addLast(int e) {
//要先判断是否有空间来容纳新元素
/*if(size==data.length){
throw new IllegalArgumentException("AddLast failed,array is full");
}
data[size]=e;
size++;*/
add(size,e);
}
//在所有元素前添加新元素
public void addFirst(int e){
add(0,e);
}
//在index位置插入元素
public void add(int index,int e){
if(size==data.length){
throw new IllegalArgumentException("Add failed,array is full");
}
if(index<0 || index>size){
throw new IllegalArgumentException("Add Failed,0<=index<=size is required");
}
//index位置后的元素向右移动
for(int i=size;i>index;i--){
data[i]=data[i-1];
}
data[index]=e;
size++;
}
//获取index位置的元素
public int get(int index){
if(index<0 || index>=size){
throw new IllegalArgumentException("Get failed,index is illegal");
}
return data[index];
}
//设置index位置元素值为e
public void set(int index,int e){
if(index<0 || index>=size){
throw new IllegalArgumentException("Get failed,index is illegal");
}
data[index]=e;
}
@Override
public String toString(){
StringBuilder builder=new StringBuilder();
builder.append(String.format("Array size=%d,capacity=%d\n",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();
}
//查找数组中是否有元素e,有就返回下标,没有就返回-1
public boolean contains(int e){
for(int i=0;i<size;i++){
if(data[i]==e){
return true;
}
}
return false;
}
//查找数组中元素e所在索引
public int find(int e){
for(int i=0;i<size;i++){
if(data[i]==e){
return i;
}
}
return -1;
}
//删除指定位置元素
public int remove(int index){
if(size==0){
throw new IllegalArgumentException("Remove failed,array is empty");
}
if(index<0 || index>=size){
throw new IllegalArgumentException("Remove failed,index is illegal");
}
int ret=data[index];
for(int i=index+1;i<size;i++){
data[i-1]=data[i];
}
size--;
return ret;
}
public int removeFirst(){
return remove(0);
}
public int removeLast(){
return remove(size-1);
}
public void removeElement(int e){
int index=find(e);
if(index!=-1){
remove(index);
}
}
调整数组大小
- 准备一个新数组,长度是原来数组的2倍
- 将原来数组中的元素复制到新数组中
- 将data指向newData,完成扩容
- 完成扩容,capacity是原来的2倍,size不变,数组中数据不变
//动态调整数组大小
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 int remove(int index){
/*if(size==0){
throw new IllegalArgumentException("Remove failed,array is empty");
}*/
if(size==data.length/2){
resize(data.length/2);
}
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;//loitering objects
return ret;
}
//在index位置插入元素
public void add(int index,E e){
/* if(size==data.length){
throw new IllegalArgumentException("Add failed,array is full");
}*/
if(size==data.length){
resize(data.length*2);
}
if(index<0 || index>size){
throw new IllegalArgumentException("Add Failed,0<=index<=size is required");
}
//index位置后的元素向右移动
for(int i=size;i>index;i--){
data[i]=data[i-1];
}
data[index]=e;
size++;
}
操作 | 时间复杂度 |
---|---|
添加操作 | 平均时间复杂度:O(n) |
addLast(e) | O(1) |
addFirst(e) | O(n) |
add(index) | O(n) |
删除操作 | 平均时间复杂度:O(n) |
removeLast(e) | O(1) |
removeFirst(e) | O(n) |
remove(index,e) | O(n) |
修改操作 | |
set(index,e) | O(1) |
查找操作 | |
get(index) | O(1) |
contains(e) | O(n) |
find(e) | O(n) |
假设capacity=n,n+1次进行addLast操作,会触发resize, 总共进行2*n+1次基本操作。
平均情况下,每次addLast操作,进行2次基本操作。
这样均摊计算,时间复杂度是O(1)。
所以addLast的均摊复杂度是 O(1)。
同理,removeLast的均摊复杂度是O(1)。
- 复杂度震荡:
- 出现问题的原因:removeLast时resize过于着急。
解决方法:lazy
当 size==capacity/4 时,才将capacity减半。
//删除指定位置元素
public int remove(int index){
/*if(size==0){
throw new IllegalArgumentException("Remove failed,array is empty");
}*/
/* if(size==data.length/2){
resize(data.length/2);
}*/
if(size==data.length/4 && data.length/2!=0){
resize(data.length/2);
}
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;//loitering objects,使用泛型时,进行此操作
return ret;
}