数据结构与算法之数组讲解

1,数组实现说明

   定义一个数组容量(capacity)为8,初始化4个数据1,2,3,4

   

int[] datas=new int[8];
for(int i=1;i<=4;i++){
    datas[i-1]=i;
}

此时,数据中的size为4,索引指向的第一个空闲位置索引为4,如果此时在改数组末尾增加一个元素5

datas[size]=5

size++

 

在指定索引index处插入元素

public void add(int index,int e){
    if(index<0 || index>this.size){
        throw new IllegalArgumentException("index must between 0 and size");
    }
    for(int position=size-1;position>=index;position--){
        this.datas[position+1]=this.datas[position];
    }
    this.datas[index]=e;
    this.size++;
}

 

在指定索引index处删除元素

public int remove(int index){
    if(index<0 || index>=this.size){
        throw new IllegalArgumentException("index must between 0 and size");
    }
    int ret=this.datas[index];
    for(int i=index+1;i<size;i++){
        this.datas[i-1]=this.datas[i];
    }
    size--;
    return ret;
}

 

下面给出具体的带泛型实现

2,代码实现

package com.dream21th.algorithmicdatastructure.array;


/**
 * @Auther: hp
 * @Date: 2019/9/7 15:42
 * @Description:
 */
public class MyExtendArray<E> {

    private E[] datas;

    private int size;

    /**
     * 创建有参构造函数,初始化数组容量
     * @param capacity
     */
    public MyExtendArray(int capacity){
        datas=(E[])new Object[capacity];
        size=0;
    }

    /**
     * 构造无参函数,初始化数组容量
     */
    public MyExtendArray(){
        this(10);
    }

    public int getSize(){
        return this.size;
    }

    public boolean isEmpty(){
        return this.size==0;
    }

    /**
     * 在指定索引位置加值
     * @param index
     * @param e
     */
    public void add(int index,E e){
        if(index<0 || index>this.size){
            throw new IllegalArgumentException("index must between 0 and size");
        }
        if(this.size==datas.length){
            resize(2*datas.length);
        }
        for(int position=size-1;position>=index;position--){
            this.datas[position+1]=this.datas[position];
        }
        this.datas[index]=e;
        this.size++;
    }

    private void resize(int newCapacity) {

        E[] newDatas= (E[]) new Object[newCapacity];

        for(int i=0;i<this.datas.length;i++){
            newDatas[i]=this.datas[i];
        }
        this.datas=newDatas;
    }

    /**
     * 在第一个位置加入元素
     * @param e
     */
    public void addFirst(E e){
        this.add(0,e);
    }

    /**
     * 在最后一个位置添加元素
     * @param e
     */
    public void addLast(E e){
        this.add(size,e);
    }

    public E get(int index){
        if(index<0 || index>=this.size){
            throw new IllegalArgumentException("index must between 0 and size");
        }
        return this.datas[index];
    }

    public void set(int index,E e){
        if(index<0 || index>=this.size){
            throw new IllegalArgumentException("index must between 0 and size");
        }
        this.datas[index]=e;
    }

    public boolean contain(E e){
        for(int i=0;i<size;i++){
            if(this.datas[i].equals(e)){
                return true;
            }
        }
        return false;
    }

    public int find(int e){
        for(int i=0;i<size;i++){
            if(this.datas[i].equals(e)){
                return i;
            }
        }
        return -1;
    }

    public E remove(int index){
        if(index<0 || index>=this.size){
            throw new IllegalArgumentException("index must between 0 and size");
        }
        E ret=this.datas[index];
        for(int i=index+1;i<size;i++){
            this.datas[i-1]=this.datas[i];
        }
        size--;
        this.datas[size]=null;
        if(this.size==this.datas.length/2){
            resize(this.datas.length/2);
        }
        return ret;
    }

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

    public E removeLast(){
        return remove(size-1);
    }
    
    @Override
    public String toString() {

        StringBuilder builder=new StringBuilder();
        builder.append(String.format("Array: size = %d,capacity = %d \n",this.size,this.datas.length));
        builder.append("[");
        for(int i=0;i<size;i++){
            builder.append(this.datas[i]);
            if(i!=size-1){
                builder.append(",");
            }
        }
        builder.append("]");
        return builder.toString();
    }
}

3,resize为数组动态扩缩容方式,目的是减少空间浪费,具体设计细节是当增加数据数据容量达到上限时,扩增容量到原来的2倍,当删除数据时,如果当前数组size为容量一般,自动缩到原来的二分之一(为避免复杂度震荡,此处可以采用到原容量四份之一,缩容到二分之一)

4,复杂度分析

addLast         O(1)

addFirst         O(n)                                      增加整体复杂度为O(n), 

add                O(n/2)

 

 

removeLast         O(1)

removeFirst         O(n)                                      删除整体复杂度为O(n), 

remove               O(n/2)

 

在知道索引的前提下,update和find的空间复杂度为O(1)

 

采用均摊算法计算增加和删除复杂度

 

如上图,在进行8次末尾增加数据后,在进行第九次增加数据时,会触发动态扩容,此过程的空间复杂度为

((1+1+1+1+1+1+1+1+1)+(8+1))/9

如果为n的话 (2n+1)/(n+1)

此过程算出动态扩容复杂度为O(2)

同理可以运算到动态缩容

5,复杂度空间震荡

如果采用动态缩容,采用的标准为容量的一半,此时如果在边界位置增加一个元素在删除一个元素,此时的复杂度为O(n),

要避免这类问题,可以在缩容时采用懒缩容的方式,及上面所说的采用到原容量四份之一,缩容到二分之一

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

dream21st

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值