<数据结构系列1>封装自己的数组——手写动态泛型数组(简化版ArrayList)
哈哈,距离上一次写博客已经快过去半个月了,这这这,好像有点慢啊,话不多说,开始我们的手写动态泛型数组
首先是我们自己写一个自己的动态数组类,代码如下所示:
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+1;i<size;i++) {
            data[i-1]=data[i];            //将删除元素后的每个元素向前移动,覆盖住要被删除的元素
        }
        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,今天的数据结构第一篇:封装自己的动态数组就写到这了,希望可以多多关注我接下来的博文哦
有啥问题可以直接在下方评论区留言,我已经开通了微信提醒,会第一时间回复的。
对于学习,四个字概括:至死方休!
<数据结构系列1>封装自己的数组——手写动态泛型数组(简化版ArrayList)的更多相关文章
- 三 基于Java动态数组手写队列
		
手写队列: package dataStucture2.stackandqueue; import com.lt.datastructure.MaxHeap.Queue; import dataStu ...
 - 二 基于java动态数组手写栈
		
package dataStucture2.stack; import dataStucture2.array.MyDynamicArray; /** * 基于动态数组手写栈 * 设计时,栈中仅栈顶对 ...
 - 三 基于Java数组手写循环队列
		
Code: package dataStucture2.stackandqueue; /** * 手写循环队列 * * @param <E> */ public class MyLoopQ ...
 - 教你如何使用Java手写一个基于数组实现的队列
		
一.概述 队列,又称为伫列(queue),是先进先出(FIFO, First-In-First-Out)的线性表.在具体应用中通常用链表或者数组来实现.队列只允许在后端(称为rear)进行插入操作,在 ...
 - 前端面试手写代码——JS数组去重
		
目录 1 测试用例 2 JS 数组去重4大类型 2.1 元素比较型 2.1.1 双层 for 循环逐一比较(es5常用) 2.1.2 排序相邻比较 2.2 查找元素位置型 2.2.1 indexOf ...
 - 教你如何使用Java手写一个基于链表的队列
		
在上一篇博客[教你如何使用Java手写一个基于数组的队列]中已经介绍了队列,以及Java语言中对队列的实现,对队列不是很了解的可以我上一篇文章.那么,现在就直接进入主题吧. 这篇博客主要讲解的是如何使 ...
 - No_1 手写Proxy
		
手写动态代理主要原理: userDAO=(UserDAO)Proxy.newProxyinstance(classloader,interfaces[],new MyInvocationHandler ...
 - springmvc 动态代理  JDK实现与模拟JDK纯手写实现。
		
首先明白 动态代理和静态代理的区别: 静态代理:①持有被代理类的引用 ② 代理类一开始就被加载到内存中了(非常重要) 动态代理:JDK中的动态代理中的代理类是动态生成的.并且生成的动态代理类为$Pr ...
 - 05-02 Java 一维数组、内存分配、数组操作
		
数组的定义 动态初始化 /* 数组:存储同一种数据类型的多个元素的容器. 定义格式: A:数据类型[] 数组名; B:数据类型 数组名[]; 举例: A:int[] a; 定义一个int类型的数组a变 ...
 
随机推荐
- 我对git的快速使用和理解
			
收藏较好的,分享给大家 https://mp.weixin.qq.com/s/k4tU8snvssyKJ2WkvkFrZA
 - 检查oracle用户默认密码的账户
			
1. 检查使用默认用户密码的账号 --11g 通过数据字典SYS.DEFAULT_PWD$或视图DBA_USERS_WITH_DEFPWD select u.username, u.account_s ...
 - [HNOI2005]汤姆的游戏
			
嘟嘟嘟 直接O(n ^ 2)暴力判断就行了. 对于圆,判断该点和圆心的距离是否小于半径. 然而为啥我这么写编译不过: scanf("%lf%lf%lf%lf", &a[++ ...
 - 利用MATLAB软件对数码相机进行检校
			
分享资料:https://pan.baidu.com/s/1FQb-ttLJNJKlMzu-0RjBsw.内部包含张正友的经典论文等文献,官网的checkerboardPattern等.
 - 关于VS2010 C#使用DirectX的问题[英]
			
转载的,就不翻译了…微软把精力放到xna去了.所以推荐大家用XNA,如果非要用托管的DirectX也可以,只不过版本一直是2006年的了. 具体方法: 安装SDK之后 他默认的位置在C:\WINDOW ...
 - PAT乙级1001
			
https://pintia.cn/problem-sets/994805260223102976/problems/994805325918486528 #include<bits/stdc+ ...
 - Spring Cloud和Dubbo整合开发笔记(1)
			
一.需求背景: 公司内部老项目微服务技术栈使用Dubbo, 新项目技术栈使用主流的Spring Cloud相关组件开发,新旧项目涉及交互调用,无法直接通信数据传递. 老项目基于Dubbo,重构代码升级 ...
 - 第一次码java感想及前三次作业总结
			
写在前面 嗯,首先是java,这学期第一次oo作业布置下来的周末才开始看的,第一次作业因此写得有些手忙脚乱.不过大概看了一遍后发现比c好用,入门更简单吧,好多操作直接import一下就能用了,码代码的 ...
 - php基础知识考察点:自定义函数及内部函数考察点
			
1.变量的作用域和静态变量 函数的参数以及参数的引用传递 函数的返回值以及引用返回 外部文件的导入 系统内置函数的考察 变量的作用域也称为变量的范围,变量的范围即他定义上下文的背景(也是它生效的范围) ...
 - Android TV 全屏无标题
			
想要全部窗口全屏无标题,修改 res\values\styles.xml 可设置主题和样式 <resources> <!-- Base application theme, depe ...