1、动态数组

1、动态数组

  • 一、什么是数据结构❓
    • 1、线性结构
    • 2、树形结构
    • 3、图形结构
  • 二、线性表
  • 三、数组(Array)
  • 四、动态数组(Dynamic Array)
    • 1、接口设计
    • 2、动态数组的设计
    • 3、查
      • (1) size、isEmpty
      • (2) indexOf、contains
      • (3) get、checkIndex
    • 4、增
      • (1) 增加元素到尾部
      • (2) 往索引位置添加元素
      • (3) 扩容
    • 5、打印数组
    • 6、删
      • (1) remove(int index)
      • (2) 对象数组
      • (3) clear
    • 7、改
    • 8、缩容

一、什么是数据结构❓

📕 数据结构是计算机存储组织数据的方式

1、线性结构

在这里插入图片描述

🖊 线性表(数组、链表、栈、队列、哈希表)

2、树形结构

在这里插入图片描述

🖊 二叉树
🖊 AVL树
🖊 红黑树
🖊 B树
🖊 堆
🖊 Trie
🖊 哈夫曼树
🖊 并查集

3、图形结构

在这里插入图片描述

🖊 邻接矩阵
🖊 邻接表

二、线性表

📕 线性表是具有 n 个相同类型元素的有限序列n ≥ 0
在这里插入图片描述
🖊 a1 是首节点(首元素), an 是尾节点(尾元素)
🖊 a1 是 a2 的前驱, a2 是 a1 的后继

🖊 常见的线性表有:
① 数组
② 链表
③ 栈
④ 队列
⑤ 哈希表(散列表)

三、数组(Array)

📕 数组是一种顺序存储的线性表,所有元素的内存地址连续

int[] array = new int[]{11, 22, 33};

在这里插入图片描述

🖊 数组缺点:
① 无法动态修改容量
② 操纵元素的方式不够面向对象

四、动态数组(Dynamic Array)

1、接口设计

在这里插入图片描述

public interface List<E> {
    /**
     * 返回存储的元素数量
     */
    int size();

    /**
     * 是否为空
     */
    boolean isEmpty();

    /**
     * 是否包含给定元素
     */
    boolean contains(E element);

    /**
     * 返回索引位置的元素
     */
    E get(int index);

    /**
     * 返回指定元素的索引
     */
    int indexOf(E element);

    /**
     * 添加元素到尾部
     */
    void add(E element);

    /**
     * 往索引位置添加元素
     */
    void add(int index, E element);

    /**
     * 删除索引位置的元素
     *
     * @return 被删除的元素
     */
    E remove(int index);

    /**
     * 清空所有元素
     */
    void clear();

    /**
     * 设置索引位置的元素
     */
    E set(int index, E element);
}

2、动态数组的设计

在这里插入图片描述

🖊 动态数组内部维护 size 成员变量,用于存储动态数组中元素的数量
🖊 动态数组内部维护 elements 成员变量,它存储着一个普通数组的内存地址

/**
 * 动态数组
 */
public class ArrayList<E> {
    public static final int DEFAULT_CAPACITY = 10;

    private int size;
    private E[] elements;

    public ArrayList() {
        this(DEFAULT_CAPACITY);
    }

    @SuppressWarnings("unchecked")
    public ArrayList(int capacity) {
        capacity = Math.max(capacity, DEFAULT_CAPACITY);
        elements = (E[]) new Object[capacity];
    }
}

3、查

(1) size、isEmpty

  /**
   * 返回存储的元素数量
   */
  @Override
  public int size() {
      return size;
  }

  /**
   * 是否为空
   */
  @Override
  public boolean isEmpty() {
      return size == 0;
  }

(2) indexOf、contains

 /**
   * 返回指定元素的索引
   */
  @Override
  public int indexOf(E element) {
      if (element == null) {
          for (int i = 0; i < size; i++) {
              if (elements[i] == null) return i;
          }
      } else {
          for (int i = 0; i < size; i++) {
              if (element.equals(elements[i])) return i;
          }
      }
      return ELEMENT_NOT_FOUND;
  }

👆 若给定的元素为 null,遍历 elements 数组的每个元素,若某个元素为 null,则返回该元素的索引
👆 若给定的元素不为 null,遍历 elements 数组的每个元素,用给定元素调用 equals() 方法和数组的每个元素比较,若 equals 方法返回 true,则返回当前元素的索引
👆 若整个 if-else 执行完毕后依然没有返回,则返回 ELEMENT_NOT_FOUND(实际是常量 -1

  /**
   * 是否包含给定元素
   */
  @Override
  public boolean contains(E element) {
      return indexOf(element) != ELEMENT_NOT_FOUND;
  }

👆 若调用 indexOf 方法后返回值不为 ELEMENT_NOT_FOUND 则动态数组中包含给定元素

(3) get、checkIndex

  private void checkIndex(int index) {
      if (index < 0 || index >= size)
          throw new IllegalArgumentException("index=" + index + ", size=" + size);
  }

👆 检查参数索引 index 是否符合规范
👆 不符合则抛异常

  /**
   * 返回索引位置的元素
   */
  @Override
  public E get(int index) {
      checkIndex(index);
      return elements[index];
  }

👆 直接通过给定索引返回 index 位置的元素

4、增

(1) 增加元素到尾部

在这里插入图片描述

🖊 添加元素到尾部:往数组的 size 位置添加元素

  /**
   * 添加元素到尾部
   */
  @Override
  public void add(E element) {
      elements[size] = element;
      size++;
  }

(2) 往索引位置添加元素

🖊 add(int index, E element) 接口的 index 可以等于 size

  private void checkIndex4Add(int index) {
      if (index < 0 || index > size)
          throw new IllegalArgumentException("index=" + index + ", size=" + size);
  }

在这里插入图片描述

🖊 把 [index, size-1] 范围内的元素全部往后挪,把 index 位置空置出来【从size-1开始挪】
🖊 把 element 添加到 index 位置

  /**
   * 往索引位置添加元素
   */
  @Override
  public void add(int index, E element) {
      checkIndex4Add(index);

      // 把index位置空出来
      for (int i = size - 1; i >= index; i--) {
          elements[i + 1] = elements[i];
      }

      // 把element添加到index位置
      elements[index] = element;
      size++;
  }

(3) 扩容

在这里插入图片描述

🖊 创建容量更大的新数组,把原来数组的元素复制到新数组中
🖊 elements 指向新数组

  @SuppressWarnings("all")
  private void ensureCapacity(int capacity) {
      int oldCap = elements.length;
      if (oldCap >= capacity) return; // 无需扩容

      // 新容量为旧容量的1.5倍
      int newCap = oldCap + (oldCap >> 1);
      // 创建新数组
      E[] newElements = (E[]) new Object[newCap];
      // 把旧数组元素复制到新数组中
      for (int i = 0; i < size; i++) {
          newElements[i] = elements[i];
      }

      elements = newElements;
  }

在这里插入图片描述

5、打印数组

◼ 重写 toString 方法
◼ 在 toString 方法中将元素拼接成字符串
◼ 字符串拼接建议使用 StringBuilder

  @Override
  public String toString() {
      StringBuilder string = new StringBuilder();
      string.append("🖊size=").append(size).append(", [");
      
      for (int i = 0; i < size; i++) {
          if (i != 0) {
              string.append(", ");
          }

          string.append(elements[i]);
      }
      string.append("]");
      return string.toString();
  }

6、删

(1) remove(int index)

在这里插入图片描述

🖊 从 [index+1, size-1] 范围内的元素全部往前赋值,覆盖掉 index 位置的元素
🖊 size--

  /**
   * 删除索引位置的元素
   *
   * @return 被删除的元素
   */
  @Override
  public E remove(int index) {
      checkIndex(index);
      E old = elements[index];

      // 覆盖
      for (int i = index + 1; i < size; i++) {
          elements[i - 1] = elements[i];
      }

      // 👇elements[--size] = null;
      size--;
      elements[size] = null;

      return old;
  }

(2) 对象数组

🖊 对象数组的每个元素存储的是对象的内存地址

在这里插入图片描述

(3) clear

🖊 把数组中的每个元素都设置为 null
🖊 size 成员变量设置为 0

  /**
   * 清空所有元素
   */
  @Override
  public void clear() {
      for (int i = 0; i < size; i++) {
          elements[i] = null;
      }
      size = 0;
  }

7、改

  /**
   * 设置索引位置的元素
   */
  @Override
  public E set(int index, E element) {
      checkIndex(index);

      E old = elements[index];
      elements[index] = element;
      return old;
  }

8、缩容

◼ 如果内存使用比较紧张,动态数组有比较多的剩余空间,可以考虑进行缩容操作
◼ 比如剩余空间占总容量的一半时,就进行缩容

  @SuppressWarnings("all")
  private void trim() {
      int curCap = elements.length;

      int halfCap = curCap >> 1;
      if (halfCap > size) {
          E[] newElements = (E[]) new Object[halfCap];
          // 把旧数组元素复制到新数组中
          for (int i = 0; i < size; i++) {
              newElements[i] = elements[i];
          }

          elements = newElements;
          System.out.println("🖊缩容:" + curCap + "→" + halfCap);
      }
  }

🍀 该文章的完整代码

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/495961.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

实力上榜 | 创新微MinewSemi再获“物联之星”年度企业投资价值50强

近日&#xff0c;由深圳市物联传媒有限公司、AIoT星图研究院、IOTE组委会、深圳市物联网产业协会主办的“物联之星”2023中国物联网行业年度榜单评选结果正式公布。经过层层筛选&#xff0c;创新微MinewSemi获评2023年度“中国物联网企业投资价值50强”&#xff0c;连续两年实力…

应急响应实战笔记04Windows实战篇(1)

第1篇&#xff1a;FTP暴力破解 0x00 前言 ​ FTP是一个文件传输协议&#xff0c;用户通过FTP可从客户机程序向远程主机上传或下载文件&#xff0c;常用于网站代码维护、日常源码备份等。如果攻击者通过FTP匿名访问或者弱口令获取FTP权限&#xff0c;可直接上传webshell&#…

Redis 不再“开源”:中国面临的挑战与策略应对

Redis 不再“开源”&#xff0c;使用双许可证 3 月 20 号&#xff0c;Redis 的 CEO Rowan Trollope 在官网上宣布了《Redis 采用双源许可证》的消息。他表示&#xff0c;今后 Redis 的所有新版本都将使用开源代码可用的许可证&#xff0c;不再使用 BSD 协议&#xff0c;而是采用…

WPF自定义Panel:让拖拽变得更简单

在 WPF 应用程序中&#xff0c;拖放操作是实现用户交互的重要组成部分。通过拖放操作&#xff0c;用户可以轻松地将数据从一个位置移动到另一个位置&#xff0c;或者将控件从一个容器移动到另一个容器。然而&#xff0c;WPF 中默认的拖放操作可能并不是那么好用。为了解决这个问…

http接口测试—自动化测试框架设计(超详细)

&#x1f345; 视频学习&#xff1a;文末有免费的配套视频可观看 &#x1f345; 关注公众号【互联网杂货铺】&#xff0c;回复 1 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 一、测试需求描述 对服务后台一系列的http接口功能测试。 …

【Git篇】复习git

文章目录 &#x1f354;什么是git⭐git和svn的区别 &#x1f354;搭建本地仓库&#x1f354;克隆远程仓库&#x1f6f8;git常用命令 &#x1f354;什么是git Git是一种分布式版本控制系统&#xff0c;它可以追踪文件的变化、协调多人在同一个项目上的工作、恢复文件的旧版本等…

微信开发者工具创建一个小程序

创建项目 对于上面这个AppID可以自行选择是注册还是测试号&#xff0c;我是使用的测试号&#xff0c;之后再下面选择模板&#xff0c;我这里选择了JS-基础模板。 进入项目后在模拟器中可看到如下页面&#xff1a; 添加提交按钮进行页面跳转 添加需要跳转的文件夹&#xff0c;…

更新时间后OpenStack neutron 401 Unauthorized解决办法

发现时间跟现实时间有偏差&#xff0c;用 ntpdate cn.pool.ntp.org 更新时间后再用neutron 发现报错 401-{uerror: {umessage: uThe request you have made requires authentication., ucode: 401, utitle: uUnauthorized}} 而且用的是账号密码的认证&#xff0c;还是无法正…

跑通飞浆平台的MTMCT 跨镜跟踪示例

想跑通飞浆平台的MTMCT跨镜跟踪示例&#xff0c;真的是难上加难啊&#xff01; 改了几处代码&#xff0c;可以顺利跑通了&#xff0c;特此记录&#xff1a; 第一处&#xff1a;不要拉主线的代码&#xff0c;改成 !git clone https://gitee.com/paddlepaddle/PaddleDetection…

Wagtail-基于Python Django的内容管理系统CMS实现公网访问

目录 ⛳️推荐 前言 1. 安装并运行Wagtail 1.1 创建并激活虚拟环境 2. 安装cpolar内网穿透工具 3. 实现Wagtail公网访问 4. 固定Wagtail公网地址 ⛳️推荐 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给…

【vue3学习笔记(一)】vue3简介;使用vue-cli创建工程;使用vite创建工程;分析工程结构;安装开发者工具

尚硅谷Vue2.0Vue3.0全套教程丨vuejs从入门到精通 对应课程136-140节 课程 P136节 《vue3简介》笔记 课程 P137节 《使用vue-cli创建工程》笔记 官方文档&#xff1a; https://cli.vuejs.org/zh/guide/creating-a-project.html#vue-create官方文档地址 查看vue-cli版本&#x…

人大金仓数据库介绍与使用指南

人大金仓数据库是一款强大的关系型数据库管理系统&#xff0c;具有简单易用、高性能和稳定可靠的特点。本文将介绍人大金仓数据库的安装方法、常用的SQL语法以及相关工具的使用。 一、安装方法&#xff1a; 1、下载人大金仓数据库安装程序&#xff1b; 2、运行安装程序&#…

Visio中存在问题的解决方法

公式缩放 mathtype公式在visio缩放之后&#xff0c;出现了变形。 解决方法&#xff1a;每次输入公式都通过 插入->对象->mathType Equation 新建一个公式。可以避免 注&#xff1a;网上有的说在word中使用mathtype编写公式&#xff0c;之后复制到visio中。 插入波形 选择…

如何制定具有挑战性的绩效目标,同时又能激励员工积极投入工作?

在现代企业管理中&#xff0c;绩效目标的设定不仅是评价员工工作成果的依据&#xff0c;更是激励员工积极投入工作的重要手段。然而&#xff0c;如何制定出既具有挑战性又能激励员工的目标&#xff0c;往往成为管理者需要深思熟虑的问题。本文将探讨如何平衡这两点&#xff0c;…

matplotlib 绘图

matplotlib 绘图 方便设置legend图例的位置 ax1.legend(loc‘upper center’, bbox_to_anchor(0.3, -0.1)) ax2.legend(loc‘upper center’, bbox_to_anchor(0.6, -0.1)) import numpy as np import matplotlib.pyplot as plt from scipy.stats import norm from scipy.inter…

金融案例:构建高效统一的需求登记与管理方案

在金融行业数字化转型背景下&#xff0c;银行等金融机构面临着业务模式创新与数据应用的深度融合。业务上所需要的不再是单纯的数据&#xff0c;而是数据背后映射的业务趋势洞察&#xff0c;只有和业务相结合转化为业务度量指标&#xff0c;经过数据分析处理呈现为报表进行展示…

一键永久存档,帕鲁冒险永不丢失

天生不爱笑的瞅什魔、最强打手炎魔羊、跑图之王云海鹿、万能配种棉悠悠...... 真的永远不想和这些可爱的帕鲁说再见&#xff5e; 那么&#xff0c;如果服务器快过期了&#xff0c;如何永久保存游戏&#xff0c;保留我们和帕鲁的美好回忆呢&#xff1f;本教程说明如何使用轻量对…

如何利用OpenCV4.9 更改图像的对比度和亮度

返回&#xff1a;OpenCV系列文章目录&#xff08;持续更新中......&#xff09; 上一篇&#xff1a;使用 OpenCV 添加&#xff08;混合&#xff09;两个图像 下一篇:如何利用OpenCV4.9离散傅里叶变换 ​目标 在本教程中&#xff0c;您将学习如何&#xff1a; 访问像素值用零…

鸿蒙OS开发实例:【工具类封装-首选项本地存储】

import dataPreferences from ohos.data.preferences; import bundleManager from ohos.bundle.bundleManager; 本地首选项数据的保存&#xff0c;利用key value 【使用要求】 DevEco Studio 3.1.1 Release api 9 【使用示例】 1、app启动时&#xff0c;从本地读取数据&…

Spring Integration 是什么?

Spring Integration 是什么&#xff1f; Spring Integration 在 Spring 家族不太有名气&#xff0c;如果不是有需求&#xff0c;一般也不会仔细去看。那么 Spring Integration 是什么呢&#xff1f;用官方的一句话来解释就是&#xff1a;它是一种轻量级消息传递模块&#xff0…
最新文章