自己动手写数据结构之封装动态数组

版权声明:本文为博主原创文章,转载请附带本文链接 https://blog.csdn.net/qq_37933685/article/details/81427609

自己动手写数据结构之封装动态数组

环境

jdk1.8

IntellJ IDEA 2018.2

封装动态数组Array

类图

1533119824072

类结构解析

成员变量

  1. data E[]

这是一个基于java数组的一个泛型数组,是Array中的存储数组的成员变量。

  1. size int

这是size,用于记录这个动态数组的大小,即数组中元素个数

成员方法

  1. getSize()

    获取元素中的元素个数

  2. getCapacity()

    获取数组的容量

  3. isEmpty()

    判断数组是否为空,即有没有元素

  4. toArray()

    将动态数组转化为普通数组

  5. addFirst(E element)

    向数组头部插入元素

  6. addFirst(E element)

    向数组头部插入元素

  7. addLast(E element)

    向数组末尾添加一个元素

  8. add(int index, E element)

    向数组指定位置插入元素

  9. get(int index)

    根据index返回值

  10. set(int index, E element)

    设置指定位置的元素

  11. contains(E element)

    数组中是否包含某个元素

  12. findOne(E element)

    查找数组中包含该元素的索引

  13. findAll(E element)

    从数组中查找某个元素,返回该元素的全部索引。没有则返回空

  14. remove(int index)

    从数组中删除指定位置的元素,并返回删除的元素

  15. removeAny(int[] indexs)

    根据索引删除多个元素

  16. removeFirst()

从数组中删除第一个元素,并返回第一个元素

  1. removeLast()

    从数组中删除最后一个元素,并返回最后一个元素

  2. removeOneElement(E element)

    从数组中删除一个这个元素,有就删除,没有则不改变。有多个则删除一个

  3. removeAllElement(E element)
    移除数组中所有是element的元素

  4. resize(int newCapacity)
    动态增加容量

  5. lazyResize()
    懒增加容量,保证有空闲的容量。

  6. swap(int i,int j)
    交换数组中两个元素的位置

码云地址:https://gitee.com/suwenguang/test.git

时间复杂度分析

操作 时间复杂度
想任意位置增加元素:add(int index, E element) 不扩容情况O(n),需要扩容O( n 2 )
删除任意位置的元素:remove(int index) 不扩容情况O(n),需要扩容O( n 2 )
查询任意位置的元素:get(int index) O(1)
修改任意位置的元素:set(int index, E element) O(1)

源码

package 数据结构.数组;

import java.util.Arrays;

/**
 * @author Veng Su [email protected]
 * @date 2018/7/15 10:51
 */
public class Array <E>{
    private E[] data;
    private int size;

    /**
     * 构造函数,传入数组容量capacity构造一个数组
     *
     * @param capacity 数组容量
     */
    public Array(int capacity) {
        data = (E[]) new Object[capacity];
    }
    public Array(E[] arr){
        data= (E[]) new Object[arr.length];
        for (int i = 0; i < arr.length; i++) {
            data[i]=arr[i];
        }
    }

    /**
     * 无参构造函数,默认构造数组容量为10的数组
     */
    public Array() {
        data = (E[]) new Object[10];
    }

    /**
     * 获取元素中的元素个数
     *
     * @return Size 数组中的元素个数
     */
    public int getSize() {
        return size;
    }

    /**
     * 获取数组的容量
     *
     * @return 数组的容量capacity
     */
    public int getCapacity() {
        return data.length;
    }

    /**
     * 判断数组是否为空,即有没有元素
     *
     * @return 如果为空,返回true;否则返回false
     */
    public boolean isEmpty() {
        return size == 0;
    }

    /**
     * 将动态数组转化为普通数组
     *
     * @return data 普通数组
     */
    public E[] toArray() {
        E[] res = (E[]) new Object[size];
        for (int i = 0; i < size; i++) {
            res[i] = data[i];
        }
        return res;
    }

    /**
     * 向数组头部插入元素
     *
     * @param element 元素
     */
    public void addFirst(E element) {
        add(0, element);
    }

    /**
     * 向数组末尾添加一个元素
     *
     * @param element 需要添加的元素
     */
    public void addLast(E element) {
        add(size, element);
    }

    /**
     * 向数组指定位置插入元素
     *
     * @param index   指定位置
     * @param element 元素
     */
    public void add(int index, E element) {
        if (size == data.length) {
            resize((int) (1.5*size));
        }
        if (index < 0 || index > size) {
            throw new IllegalArgumentException("数组索引必须大于0,小于size的");
        }
        for (int i = size - 1; i >= index; i--) {
            data[i + 1] = data[i];
        }
        data[index] = element;
        size++;
    }

    /**
     * 根据index返回值
     *
     * @param index 索引
     * @return 元素
     */
    public E get(int index) {
        if (index < 0 || index >= size) {
            throw new IllegalArgumentException("参数错误 index: require <size&&>0");
        }
        return data[index];
    }

    public E getLast(){
        return get(size-1);
    }
    public E getFirst(){
        return get(0);
    }

    /**
     * 设置指定位置的元素
     *
     * @param index   索引
     * @param element 元素
     */
    public void set(int index, E element) {
        if (index < 0 || index >= size) {
            throw new IllegalArgumentException("参数错误 index: require <size&&>0");
        }
        data[index] = element;
    }

    /**
     * 数组中是否包含某个元素
     *
     * @param element
     * @return 是,则包含;否,则不包含
     */
    public boolean contains(E element) {
        for (E e : data) {
            if (element .equals(e) ) {
                return true;
            }
        }
        return false;
    }

    /**
     * 查找数组中包含该元素的索引
     *
     * @param element 元素
     * @return 该元素的索引,如果不存在该元素,则返回-1
     */
    public int findOne(E element) {
        for (int i = 0; i < size; i++) {
            if (data[i].equals(element)) {
                return i;
            }
        }
        return -1;
    }

    /**
     * 从数组中查找某个元素,返回该元素的全部索引。没有则返回空
     *
     * @param element 要查找的元素
     * @return
     */
    public int[] findAll(E element) {
        Array<Integer> res = new Array();
        for (int i = 0; i < size; i++) {
            if (data[i].equals(element)) {
                res.addLast(i);
            }
        }
        if (res.isEmpty()) {
            return null;
        }

        return Arrays.stream(res.toArray())
                .mapToInt(Integer::valueOf)
                .toArray();
    }

    /**
     * 从数组中删除指定位置的元素,并返回删除的元素
     *
     * @param index 指定位置
     * @return int 删除的元素
     */
    public E remove(int index) {
        if (index >= size || index < 0) {
            throw new IllegalArgumentException("参数错误 index: require <size&&>0");
        }
        E res = data[index];
        for (int i = index; i < size-1; i++) {
            data[i] = data[i + 1];
        }
        size--;
        data[size]=null;//因为remove的时候最后一个还存在一个对象的应用所以要将引用置空,让jvm的垃圾回收器可以自动回收这个垃圾对象
        //注意:loitering object !=memory leak 游荡对象不等于内存泄漏
        lazyResize();
        return res;
    }

    /**
     * 根据索引删除多个元素
     * @param indexs 元素索引
     */
    public void removeAny(int[] indexs) {
        E[] cache = (E[]) new Object[size - indexs.length];
        int newSize = 0;
        for (int i = 0; i < indexs.length + 1; i++) {
            if (i == 0) {
                if (indexs[i] != 0) {
                    System.arraycopy(data, 0, cache, newSize, indexs[i]);
                    newSize = indexs[i];
                }
            } else if (i == indexs.length) {
                if (indexs[i - 1] < size - 1) {
                    System.arraycopy(data, indexs[i - 1] + 1, cache, newSize, data.length - indexs[i - 1] - 1);
                    newSize += data.length - indexs[i - 1] - 1;
                }
            } else {
                int length = indexs[i] - indexs[i - 1] - 1;
                System.arraycopy(data, indexs[i - 1] + 1, cache, newSize, length);
                newSize += length;
            }
        }
        size = newSize;
        data = cache;
        lazyResize();
    }

    /**
     * 从数组中删除第一个元素,并返回第一个元素
     *
     * @return 以前的第一个元素
     */
    public E removeFirst() {
        return remove(0);
    }

    /**
     * 从数组中删除最后一个元素,并返回最后一个元素
     *
     * @return 以前的最后一个元素
     */
    public E removeLast() {
        return remove(size - 1);
    }

    /**
     * 从数组中删除一个这个元素,有就删除,没有则不改变。有多个则删除一个
     *
     * @param element 要删除的元素
     * @return true 则移除成功,false则数组中没有该元素
     */
    public boolean removeOneElement(E element) {
        int index = findOne(element);
        if (index != -1) {
            remove(index);
            return true;
        }
        return false;
    }

    /**
     * 移除数组中所有是element的元素
     * @param element 元素
     * @return true 则移除成功,false则数组中没有该元素
     */
    public boolean removeAllElement(E element) {
        int[] indexs = findAll(element);
        if (indexs == null) {
            return false;
        }
        removeAny(indexs);
        return true;
    }

    /**
     * 动态增加容量
     * @param newCapacity 新的容量
     */
    private void resize(int newCapacity){
        E[] newData= (E[]) new Object[newCapacity];
        System.arraycopy(data,0,newData,0,size);
        data=newData;
    }

    /**
     * 懒增加容量,保证有空闲的容量。
     */
    private  void lazyResize(){
        if (size==data.length/4&&data.length/2!=0)
            resize(data.length/2);
    }

    /**
     * 交换数组中两个元素的位置
     * @param i
     * @param j
     */
    public void swap(int i,int j){
        if (i<0||i>=size||j<0||j>=size){
            throw new IllegalArgumentException("索引错误,应该>0&&<=size");
        }
        E t=data[i];
        data[i]=data[j];
        data[j]=t;
    }

    /**
     * 设置打印格式,把size和capacity打印出来,以及data的元素
     *
     * @return String
     */
    @Override
    public String toString() {
        StringBuilder res = new StringBuilder(50);
        res.append(String.format("Array: size=%d,capasity=%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();
    }
}

猜你喜欢

转载自blog.csdn.net/qq_37933685/article/details/81427609