数组是学习编程语言时较先接触到的一种数据结构,本章基于Java的静态数组实现动态数组,并进行简单的复杂度分析

数组相信各位都知道,那什么是动态数组呢?我们定义一个数组后,一般长度会直接定义好,如果数组容量被存满,就无法再继续往数组中添加元素,动态数组则是当容量被存满,会自动进行扩容操作

添加元素后自动扩容

删除元素后自动缩容

public class Array {

private int size;

private Object[] data;

//有参构造函数,传入数组的容量capacity构造Arraypublic Array(int capacity) {

size = 0;

data = new Object[capacity];

}

//无参构造函数,调用有参构造函数,默认定义capacity数组容量为10public Array() {

this(10);

}

//获取数组中元素的个数public int getSize() {

return size;

}

//获取数组的容量public int getCapacity() {

return data.length;

}

//判断数组是否为空public boolean isEmpty() {

return size == 0;

}

//在数组的尾部添加元素public void addLast(E e) {

add(size, e);

}

//在数组的头部添加元素public void addFirst(E e) {

add(0, e);

}

//在下标为index的位置插入一个元素epublic void add(int index, E e) {

if (index < 0 || index > size)

throw new IllegalArgumentException("Add failed,index need >=0 and <=size");

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++;

}

/** 重新定义数组的容量,当数组元素增加或减少到一定条件时* 调用此方法更改数组容量,实现数组自动扩容与缩容*/

private void resize(int newCapacity) {

Object[] newData = new Object[newCapacity];

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

newData[i] = data[i];

data = newData;

}

//获取下标为index的元素public Object get(int index) {

if (index < 0 || index >= size)

throw new IllegalArgumentException("Get failed,index is illegal");

return data[index];

}

//获取第一个元素public Object getFirst() {

return get(0);

}

//移除元素epublic void removeElement(E e) {

int index = find(e);

if (index != -1)

remove(index);

}

//移除下标为index的元素,并返回被移除的元素@SuppressWarnings("unchecked")

public E remove(int index) {

if (index < 0 || index >= size)

throw new IllegalArgumentException("Remove failed,index is illegal");

if (size == data.length / 4 && data.length / 2 != 0) {

resize(data.length / 2);

}

Object temp = data[index];

for (int i = index + 1; i < size; i++) {

data[i - 1] = data[i];

}

size--;

data[size] = null;

return (E) temp;

}

//移除第一个元素并返回public E removeFirst() {

return remove(0);

}

//移除最后一个元素并返回public E removeLast() {

return remove(size - 1);

}

//判断数组中是否包含元素epublic 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;

}

@Override

public String toString() {

StringBuilder res = new StringBuilder();

res.append(String.format("Array: size = %d , capacity = %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();

}

}

简单时间复杂度分析

增:

add(index,e) O(n)

addLast(e) O(1)

addFirst(e) O(1)

取最坏的情况所以增的时间复杂度是 O(n)

删:

删除与增加同理同是 O(n)

改:

set(index,e)

已知索引的情况下是O(1),未知索引的情况下是O(n)

查:

get(index) O(1)

contains(e) O(n)

find(e) O(n)

已知索引的情况下是O(1),未知索引的情况下是O(n)

均摊复杂度分析

addLast:O(1)

当数组增加元素达到一定数量时,会调用resize方法进行扩容操作,例如:

一个容量为8的数组,当addLast调用9次时,会调用resize方法进行扩容操作,显然并不是每次addLast都会调用resize,所以说9次addLast操作会触发一次resize(给容量为8的数组扩容时,会有8次元素存入新数组的操作),总共进行了17 (9次addLast加上扩容的8次元素存入新数组的操作) 次基本操作

平均每次addLast操作,进行2 (17÷9≈2) 次基本操作

也就是说,当数组容量为n时,n+1次addLast操作会调用一次resize操作,总共2n+1次基本操作

平均每次addLast操作,进行2次基本操作

所以addLast的时间复杂度可以算是O(1)的,也就是说在均摊计算中,比计算最坏的情况有意义

removeLast:与addLast同理

复杂度的震荡

当同时思考addLast和removeLast操作的时候:

假如调用addLast触发resize扩容后调用removeLast显然也会调用resize进行缩容,这个操作如果反复执行就会导致复杂度的震荡,所以代码中removeLast方法中,并没有像addLast中那样直接让data.length/2,而是当数组内的元素等于四分之一容量的时候,才会执行缩容的操作,就可以解决复杂度的震荡

if (size == data.length / 4 && data.length / 2 != 0) {

resize(data.length / 2);

}

java动态数组的实现的_Java实现数据结构之【动态数组】相关推荐

  1. java 数据结构_Java版-数据结构-队列(数组队列)

    前言 看过笔者前两篇介绍的 Java版数据结构 数组和 栈的盆友,都给予了笔者一致的好评,在这里笔者感谢大家的认可!!! 由于本章介绍的数据结构是 队列,在队列的实现上会基于前面写的 动态数组来实现, ...

  2. java数组插入一个数_java如何在一个有序的数组类插入一个数!

    第一种:依次与有序数组中的每个数进行比较,然后找到位置之后,定义一个新的数组,该信数组的长度加一,再使用system.arraycopy将于数组copy到新数组!import java.util.Ar ...

  3. js 数组 实现 完全树_算法和数据结构 | 树状数组(Binary Indexed Tree)

    本文来源于力扣圈子,作者:胡小旭.点击查看原文 力扣​leetcode-cn.com 树状数组或二叉索引树(英语:Binary Indexed Tree),又以其发明者命名为 Fenwick 树.其初 ...

  4. java怎么判断string数组是否为空_java技术校验字符串、数组是否为空、空字符串...

    java开发中你经常会遇到的是字符串为空而抛出异常,这时候你就会想到如果有一个工具类可以校验一下如果是空或者是空字符串.我则跳过去不走这个方法或者返回错误信息.下面给大家分享校验空值.空字符串的几个方 ...

  5. java删除数组中指定元素_java学习中如何删除数组中的指定元素

    java的api中,并没有提供删除数组中元素的方法.虽然数组是一个对象,不过并没有提供add()remove()或查找元素的方法.这就是为什么类似ArrayList和HashSet受欢迎的原因. 不过 ...

  6. java数组有顺序吗_java – 使用特定顺序对(数组)列表进行排序

    是的,您可以创建一个 Comparator来创建排序策略,或者定义实现 Comparable的类的自然顺序 作为旁注: It is strongly recommended,but not stric ...

  7. java char 动态数组_Java程序来填充char数组中的元素

    可以使用java.util.Arrays.fill()方法将元素填充到char数组中.此方法将所需的char值分配给Java中的char数组.所需的两个参数是数组名称和要存储在数组元素中的值. 演示此 ...

  8. java 二维链表_Java数据结构与算法----数组与链表

    数据类型 1 数据类型介绍 数据类型的分类(按照结构划分):线性结构和非线性结构 线性结构:线性结构作为最常用的数据结构,其特点是数据元素之间存在一对一的线性关系 线性结构有两种不同的存储结构,即顺序 ...

  9. java数组元素是类_Java数组及其常用类

    本文由疯狂软件教育中心整理,更多Java等高新技术,疯狂软件期待与你交流. 一.JAVA中的数组 (1)数组的定义:是有相同类型的.用一个标识符名称封装到一起的一个对象序列或基本数据类型数据序列. 数 ...

最新文章

  1. js改变img标签的src属性在IE下没反应的解决方法
  2. 推荐算法-聚类-K-MEANS
  3. 微软公布 Windows Phone 8 多项新特性
  4. Android 编程下的四大组件之服务(Service)
  5. JavaWeb学习路线(总结自尚硅谷雷神SSM|极其详细|思路清晰|适合入门/总复习)
  6. C#中check和uncheck
  7. java对接企业微信
  8. php类 汉子转拼音 通讯录按字母顺序排列
  9. Android 图片自动放大/缩小循环执行
  10. FlashPaper组件——api
  11. 精读《算法 - 动态规划》
  12. 《黑马程序员》通讯录管理系统实战
  13. vim autoformat php,将Vim打造成Python IDE(二):代码格式化的一些问题
  14. AF BAF tuning <5>
  15. Docker Compose 容器编排基础使用
  16. android studio模拟手机黑屏,Android Studio 模拟器启动问题——黑屏 死机 解决方法...
  17. Jenkins服务器实战-臧雪园-专题视频课程
  18. 创建学生、课程、老师、学生成绩表
  19. 面向接口进行开发,而不是面向实现
  20. 张飞硬件第四部(二)

热门文章

  1. C++之父Bjarne Stroustrup:程序员在数学上付出的努力,永远也不会白费
  2. 苹果硬件技术高级副总裁揭露:自研 M1 太难了
  3. Java 8 八年不倒、IntelliJ IDEA 力压 Eclipse,2022 年 Java 开发者都在用什么?
  4. 【历史上的今天】8 月 13 日:Oracle 起诉 Google,Java 版权案正式开启!
  5. 打造 AI 语音新标杆,英特尔与腾讯云小微创新共赢
  6. 2021 最新的 Web 开发趋势
  7. 明晚 8 点,为你揭秘「AI 换脸术」:剧照 or 视频换脸背后的核心技术与应用
  8. 云原生的基石,一文读懂容器、Docker、Pod到底是什么!
  9. Excel弱爆了!这个工具30分钟完成了我一天的工作量!
  10. 每位初级开发都应该知道的六件大事