<数据结构系列1>封装自己的数组——手写动态泛型数组

哈哈,距离上一次写博客已经快过去半个月了,这这这,好像有点慢啊,话不多说,开始我们的手写动态泛型数组

首先是我们自己写一个自己的动态数组类,代码如下所示:

public class Array<E> {
    //成员变量:数据,大小
    private E[] data;
    private int size;
    
    //构造函数,传入数组的容量capacity
    public Array(int capacity) {
        data=(E[])new Object[capacity];
        size=0;
    }
    
    //无参构造函数,默认capacity=10
    public Array() {
        this(10);
    }
    
    //获取数组的容量
    public int getCapacity() {
        return data.length;
    }
    
    //获取数组中的元素个数
    public int getSize() {
        return this.size;
    }
    
    //返回数组是否为空
    public boolean isEmpty() {
        return size==0;
    }
    
    //在index索引的位置插入一个新元素e
    public void add(int index,E e) {
        if(index<0||index>size)
            throw new IllegalArgumentException("Add faild.Require index >=0 and index <=size");
                    //IllegalArgumentException 非法数据异常
                
        if(size==data.length)
            resize(data.length*2);//动态扩大数组容量
                
        for(int i=size-1;i>=index;i--) {
            data[i+1]=data[i];            //插入的位置后的元素都应该向后移位
        }
        data[index]=e;
        size++;
    }
    
    
    //向所有元素后添加一个新元素e
    public void addLast(E e) {
        add(size,e);
    }
    
    //在所有元素前添加一个新元素e
    public void addFirst(E e) {
        add(0,e);
    }
    
    
    //获取index索引位置的元素
    public E get(int index) {
        if(index<0||index>=size)
            throw new IllegalArgumentException("Get faild.Index is illegal.");
        return data[index];
    }
    
    //修改index索引位置的元素为e
    public void set(int index,E e) {
        if(index<0||index>=size)
            throw new IllegalArgumentException("Set faild.Index is illegal.");
        data[index]=e;
    }
    
    //查找数组中是否有元素e
    public boolean contain(E e) {
        for(int i=0;i<size;i++) {
            if(data[i].equals(e))
                return true;
        }
        return false;
    }
    
    //查找数组中元素e所在的索引,如果不存在元素e则返回-1
    public int find(E e) {
        for(int i=0;i<size;i++) {
            if(data[i].equals(e))
                return i;
        }
        return -1;
    }
    
    //从数组中删除index位置的元素,返回删除的元素
    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;i<size;i++) {
            data[i]=data[i+1];            //将删除元素后的每个元素向前移动,覆盖住要被删除的元素
        }
        size--;
        data[size]=null;                //将最后的引用设为null,否则空间无法回收
        
        
        if(size==data.length/4&&data.length/2!=0)//这里是当元素数量等于容量的1/4时,进行缩容操作
            resize(data.length/2);
        
        return ret;
    }
    
    //从数组中删除第一个元素,返回删除的元素
    public E removeFirst() {
        return remove(0);
    }
    
    //从数组中删除最后一个元素,返回删除的元素
    public E removeLast() {
        return remove(size-1);
    }
    
    //从数组中删除元素e
    public void removeElement(E e) {
        int index=this.find(e);
        if(index!=-1)
            remove(index);
    }
    
    //将数组空间的容量变为newCapacity
    private void resize(int newCapacity) {
        E[] newData= (E[])new Object[newCapacity];
        for(int i=0;i<size;i++) {
            newData[i]=data[i];
        }
        data=newData;    //data指向newData
    }
    
    //重写tostring方法
    @Override
    public String toString() {
        StringBuffer res=new StringBuffer();
        res.append('[');
        for(int i=0;i<size;i++) {
            res.append(data[i]);
            if(i!=size-1)
                res.append(", ");
        }
        res.append(']');
        return res.toString();
    }
    
}

 接着在写一个测试方法:

public class Main {

    public static void main(String[] args) {
        Array<Integer> arr=new Array<>();
        for(int i=0;i<10;i++)
            arr.addLast(i);    //向数组尾部添加10个元素
        System.out.println(arr);//打印
        System.out.println("---------------------------");
        arr.add(1, 100);    //向下标为1的位置添加元素100
        System.out.println(arr);
        System.out.println("---------------------------");
        arr.addFirst(-1);    //向数组头部添加
        System.out.println(arr);
        System.out.println("---------------------------");
        arr.remove(2);        //删除下标2的元素
        System.out.println(arr);
        System.out.println("---------------------------");
        arr.removeElement(4);    //删除元素4
        System.out.println(arr);
        System.out.println("---------------------------");
        arr.removeFirst();    //删除第一个元素
        System.out.println(arr);
        System.out.println("---------------------------");
        for(int i = 0 ; i < 4 ; i ++){
            arr.removeFirst();    
            System.out.println(arr);
        }
    }

}

输出:

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
---------------------------
[0, 100, 1, 2, 3, 4, 5, 6, 7, 8, 9]
---------------------------
[-1, 0, 100, 1, 2, 3, 4, 5, 6, 7, 8, 9]
---------------------------
[-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
---------------------------
[-1, 0, 1, 2, 3, 5, 6, 7, 8, 9]
---------------------------
[0, 1, 2, 3, 5, 6, 7, 8, 9]
---------------------------
[1, 2, 3, 5, 6, 7, 8, 9]
[2, 3, 5, 6, 7, 8, 9]
[3, 5, 6, 7, 8, 9]
[5, 6, 7, 8, 9]


ok,这就完成了自己的动态泛型数组。

接下来分析一下时间复杂度:

//添加操作
addLast(e)    O(1)
addFirst(e)    O(n)
add(index,e)    O(n/2)=O(n)
//删除操作
removeLast(e)    O(1)
removeFirst(e)    O(n)
remove(index,e)    O(n/2)=O(n)
//修改操作
set(index,e)    O(1)
//查找操作
get(index)    O(1)
contains(e)    O(n)
find(e)    O(n)

//总结
增:O(n)    存在resize    O(n)
删:O(n)    存在resize    O(n)
改:已知索引O(1);未知索引O(n)
查:已知索引O(1);未知索引O(n)
    

ok,今天的数据结构第一篇:封装自己的动态数组就写到这了,希望可以多多关注我接下来的博文哦

有啥问题可以直接在下方评论区留言,我已经开通了微信提醒,会第一时间回复的。

对于学习,四个字概括:至死方休!

猜你喜欢

转载自www.cnblogs.com/LASloner/p/10721407.html