算法与数据结构(三)之动态数组

本文详细介绍了使用Java实现动态数组的过程,包括构造函数、添加元素、删除元素、扩容等操作。文章重点讨论了各种操作的时间复杂度,如addLast()、addFirst()、add(index, e)的最坏情况,并分析了resize()方法在扩容和缩容中的复杂度。此外,还提出了在频繁增删元素可能导致复杂度震荡的问题,并探讨了解决方案。
摘要由CSDN通过智能技术生成
package com.yan.study.algorithm.array;

import javafx.scene.control.TableView;

/**
 * 基于Java数组封装属于自己的数组类
 */
public class Array<E>{
    private E data[];
    private int size;//数组中实际有多少个元素,初始指向的位置是第一个没有元素的索引

    /**
     * 构造函数传入容量为capacity的构造Array
     * @param capacity
     */
    public Array(int capacity){
        data = (E[]) new Object[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;
    }
    //[0,1,2,3]因为数组的结构在尾部添加时最方便的
    public void addLast( E e){
//        if( size == data.length ){
//            throw new IllegalArgumentException("AddLast failed ,array is full");
//        }
//        data[size] = e;
//        size++;

        add(size,e);
    }

    //向指定的index位置插入元素
    public void add(int index, E e){
        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++;
    }



    public void addFirst(E e){
        add(0,e);
    }

    public E get(int index){
        return data[index];
    }

    void set(int index,E e){
        data[index] = e;
    }
    //是否存在某个元素e
    public boolean contains(E e){
        for (int i =0;i<size;i++){
            if(data[i].equals(e) ){
                return true;
            }
        }

        return  false;
    }
    //查找某个元素e的索引
    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("index remove failed ,index is fault");
        }
        E ret = data[index];
        //我自己的思路
//        for (int i =index;i<size;i++){
//            data[i] = data[i+1];
//        }
//
        for (int i = index+1;i<size;i++){
            data[i-1] = data[i];
        }
        size--;
        data[size] = null;
//        if(size == data.length/2){
//            resize(data.length/2);
//        }
        //防止复杂度震荡
        if(size == data.length/4){
            resize(data.length/2);
        }
        return ret;

    }
//从数组中删除元素e
    public void removeElement(E e){
        int index = find(e);
        if(index != -1){
            remove(index);
        }
    }
    public E removeLast(){
        return  remove(size-1);

    }
    public E  removeFirst(){
        return  remove(0);
    }

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

    }

    public E getFirst(){
        return get(0);
    }
    @Override
    public String toString(){
        StringBuilder result = new StringBuilder();
        result.append(String.format("array:size = %d,capacity:= %d\n",size,data.length));
        result.append("[");
        for(int i = 0; i<size;i++){
            result.append(data[i]);
            if(i != size-1){
                result.append(" ,");

            }
        }
        result.append("]");

        return result.toString();
    }

    private void resize(int newCapacity) {
        E []newData = (E[])new Object[newCapacity];

        for (int i=0; i<size; i++){

            newData[i] = data[i];
        }
        data = newData;
    }
}

动态数组的时间复杂度总体来说是O(n)级别,除了个别的O(1)。

添加操作:最坏O(n)

  • addLast()  O(1)
  • addFirst() O(n)
  • add(index,e) O(n/2) = O(n)

resize的复杂度分析

假设capacity=n,则n+1次addLast操作才会触发一次resize的O(n)操作,总共进行2n+1次基本操作,平均每次addLast操作进行2次基本操作。均摊下来复杂度变成了O(1)

但是当我们同时看,addLast和removeLast操作,频繁的增删,不断的扩缩容量,造成复杂度震荡。出现问题的原因,removeLast时resize过于着急(Eager),当size=capacity/4时才将capacity减半

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值