1. 二次封装自己的数组
基于Java的数组,二次封装属于我们自己的数组类,可以对数组进行增删改查操作。
public class Array {
private int[] data;
private int size;
public Array(int capacity){
data=new int[capacity];
size=0;
}
public Array(){
this(10);
}
public int getSize(){
return size;
}
public int getCapacity(){
return data.length;
}
public boolean isEmpty(){
return size==0;
}
}
2. 向数组中添加元素
实现向数组指定位置插入元素
public void addLast(int e){
add(size,e);
}
public void addFirst(int e){
add(0,e);
}
public void add(int index,int e){
if(size==data.length){
throw new IllegalArgumentException("add filed,Array if full");
}
if(index<0||index>size){
throw new IllegalArgumentException("add filed,Require index>=0 and index<=size");
}
for(int i=size;i>index;i--){
data[i]=data[i-1];
}
data[index]=e;
size++;
}
3.查询和修改数组元素
查询数组指定位置元素和修改指定位置元素
public int get(int index){
if(index<0||index>=size){
throw new IllegalArgumentException("get failed,index is illegal");
}
return data[index];
}
public void set(int index,int e){
if(index<0||index>=size){
throw new IllegalArgumentException("get failed,index is illegal");
}
data[index]=e;
}
4. 搜索和删除数组元素
搜索数组是否包含某个元素,删除数组中指定位置元素或者删除数组中某个元素
public boolean contains(int e){
for(int i=0;i<size;i++){
if(data[i]==e){
return true;
}
}
return false;
}
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(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);
remove(index);
}
5. 使用泛型
为了使我们封装的数组能支持更多的数据类型,这里我们使用泛型,具体修改后的代码如下:
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 int getSize(){
return size;
}
public int getCapacity(){
return data.length;
}
public boolean isEmpty(){
return size==0;
}
public void addLast(E e){
add(size,e);
}
public void addFirst(E e){
add(0,e);
}
public void add(int index,E e){
if(size==data.length){
throw new IllegalArgumentException("add filed,Array if full");
}
if(index<0||index>size){
throw new IllegalArgumentException("add filed,Require index>=0 and index<=size");
}
for(int i=size;i>index;i--){
data[i]=data[i-1];
}
data[index]=e;
size++;
}
public E get(int index){
if(index<0||index>=size){
throw new IllegalArgumentException("get failed,index is illegal");
}
return data[index];
}
public void set(int index,E e){
if(index<0||index>=size){
throw new IllegalArgumentException("get failed,index is illegal");
}
data[index]=e;
}
public boolean contains(E e){
for(int i=0;i<size;i++){
if(data[i].equals(e)){
return true;
}
}
return false;
}
public int find(E e){
for(int i=0;i<size;i++){
if(data[i].equals(e)){
return i;
}
}
return -1;
}
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;
return ret;
}
public E removeFirst(){
return remove(0);
}
public E removeLast(){
return remove(size-1);
}
public void removeElement(E e){
int index=find(e);
remove(index);
}
@Override
public String toString(){
StringBuffer res=new StringBuffer();
res.append(String.format("Array: szie = %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();
}
}
5. 动态数组
我们封装的数组是基于Java的数组,所以数组的容量是不可变的,为此我们要实现一个动态数组,使得数组的容量可以动态改变,当数组满的时候,我们可以进行扩容,当数组中所存储的数据远小于数组容量时,我们可以进行缩容,具体代码如下:
public void add(int index,E e){
if(index<0||index>size){
throw new IllegalArgumentException("add filed,Require index>=0 and index<=size");
}
if(size==data.length){
resize(2*data.length);
}
for(int i=size;i>index;i--){
data[i]=data[i-1];
}
data[index]=e;
size++;
}
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;
}
private void resize(int newCapacity){
E[] newData= (E[]) new Object[newCapacity];
for(int i=0;i<size;i++){
newData[i]=data[i];
}
data=newData;
}
6. 分析动态数组的时间复杂度
-
添加操作
addLast(e) O(1) addFirst(e) O(n) add(index,e) O(n)
总体而言动态数组的添加操作时间复杂度是O(n)
-
删除操作
removeLast() O(1) removeFirst() O(n) remove(index,e) O(n)
总体而言动态数组的删除操作时间复杂度是O(n)
-
修改操作
set(index,e) O(1)
动态数组的修改操作时间复杂度是O(1)
-
查找操作
get(index) O(1) contains(e) O(n) find(e) O(n)
总体而言动态数组的查找操作时间复杂度是O(n)
因此对于动态数组来说:添加操作和删除操作时间复杂度都是O(n),而修改操作和查找操作,在索引已知情况下时间复杂度为O(1),未知索引情况下是O(n)