数据结构——用Java实现数组

这篇具有很好参考价值的文章主要介绍了数据结构——用Java实现数组。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、什么是数据结构?

概念:

数据结构是一门基础的学科,是研究数据如何在计算机中进行组织和存储,使得我们可以高效的获取数据和修改数据的。

数据结构可以分为三类:

1.线性结构:数组、队列、栈、链表、哈希表…

2.树形结构:二叉树、二分搜索树、AVL树,红黑树、堆、Trie、线段树、并查集…

3.图结构:邻接矩阵、邻接表

为什么要学习数据结构?

好的程序是数据结构+算法来实现的:数据结构+算法=程序

在遇到不同的问题时,选择对应的数据结构方法,能更快更好的进行解决。

学习数据结构还可以锻炼我们的代码和思维能力。

二、数组

1.数组基础

  • 数组是用来存储一组类型相同的数据的集合
  • 在内存中,分配连续的空间,数组创建时要指定容量(大小)
  • 数据类型[] 数组名 int[] arr = new int[10] int[] arr2 = {1,2,3,4}
  • 索引---访问数组时通过索引进行操作 索引从0开始,最大为 arr.length -1
  • 常见的错误: NullPointException ArrayIndexOutOfBoundsException
  • 常见的数组: 字符串, 对象数组,哈希表

使用数组时,最重要的就是数组的索引,通过索引可以对数组进行改和查操作。

数组最大的优点:快速查询。

数组最好应用于索引有语义的情况。例如:通过学生学号进行查询等

2.向数组中添加元素

public void add(int item) {
        //this.size 指向的是待插入元素的位置
        this.data[this.size] = item;
        this.size++;
    }

3.向指定位置添加元素

public void addInIndex(int index, int val) {
        if (index < 0 || index > this.size) {
            throw new IllegalArgumentException("index is invalid.");
        }
        //从index位置开始元素需要进行后移
        for (int i = this.size - 1; i >= index; i--) {
            this.data[i + 1] = this.data[i];
        }
        this.data[index] = val;
        //更新this.size
        this.size++;
    }

有了向指定位置添加元素的方法后,就可以修改上面所写的尾部添加元素的方法:

public void add(int item) {
        //this.size 指向的是待插入元素的位置
        addInIndex(this.size, item);
    }

也可以写一个头部添加的方法:

 public void addHead(int item) {
        addInIndex(0, item);
    }

4.获取指定位置的元素和修改指定位置的元素

//修改指定位置的值
    public void modifyValueByIndex(int index, int value) {
        //入参一定要判断
        if (index < 0 || index >= this.size) {
            throw new IllegalArgumentException("index is invalid.");
        }
        this.data[index] = value;
    }

    //获取指定位置的值
    public int getValueByIndex(int index) {
        if (index < 0 || index >= this.size) {
            throw new IllegalArgumentException("index is invalid.");
        }
        return this.data[index];
    }

5.包含、搜索和删除元素

//查询指定的值在数组中是否存在,如查存在,获取索引,否则返回-1
    public int containsValue(int val) {
        //遍历数组
        for (int i = 0; i < this.size; i++) {
            if (val.equals(this.data[i])) {
                return i;
            }
        }
        return -1;
    }

    //删除操作
    public int removeByIndex(int index) {
        if (index < 0 || index >= this.size) {
            throw new IllegalArgumentException("index is invalid.");
        }
        //删除操作的核心
        /*
        1.找到删除的位置
        2.删除位置之后的元素要前移 arr[j-1]=arr[j]
         */
        int delValue = this.data[index];
        for (int i = index + 1; i < this.size; i++) {
            this.data[i - 1] = this.data[i];
        }
        this.size--;
        return delValue;
    }

6.打印数组

打印数组前提是重写toString方法:

 @Override
    public String toString() {
        StringBuilder sb = new StringBuilder("[");
        for (int i = 0; i < this.size; i++) {
            sb.append(this.data[i]);
            if (i != this.size - 1) {
                sb.append(",");
            }
        }
        sb.append("]");
        return sb.toString();
    }

然后写主函数,对所写的数组的方法进行调用和输出:

 public static void main(String[] args) {
        Random random = new Random();
        //向数组中添加元素
        for (int i = 0; i < 10; i++) {
            myArr.add(random.nextInt(100));
        }
        //遍历数组
        System.out.println(myArr.toString());
        //查询
        //1.索引为2的位置值是多少
        int result = myArr.getValueByIndex(2);
        System.out.println("index=2,value=" + result);
        //2.获取值为57的元素的索引
        int index = myArr.containsValue(57);
        System.out.println("57元素的索引是" + index);
        //删除值为57的元素
        if (index != -1) {
            result = myArr.removeByIndex(index);
            System.out.println(result);
        }
        System.out.println(myArr);

        //向数组中指定位置添加元素(3,99)
        myArr.addInIndex(3, 99);
        System.out.println(myArr);

       

    }

7.出现的问题和解决方法:

  1. 向数组中继续添加一个元素,就会出错(解决方法:扩容)
  2. 删除元素后,空间利用率低--(解决办法:缩容)
  3. 现在只能处理int类型,如何处理多种类型--(解决办法:泛型)

新增了一个改变容积的方法

//向数组中指定位置添加元素
    public void addInIndex(int index, int val) {
        if (index < 0 || index > this.size) {
            throw new IllegalArgumentException("index is invalid.");
        }
        //判断数组是否满
        if (this.size == this.capacity) {
            //扩容
            resize(this.capacity * 2);
        }
        //从index位置开始元素需要进行后移
        for (int i = this.size - 1; i >= index; i--) {
            this.data[i + 1] = this.data[i];
        }
        this.data[index] = val;
        //更新this.size
        this.size++;
    }

    private void resize(int newCapacity) {
        System.out.println("resize:" + newCapacity);
        T[] newData = (T[]) (new Object[newCapacity]);
        //将原数组驾到新数组里
        for (int i = 0; i < this.size; i++) {
            newData[i] = this.data[i];
        }
        //改变容器
        this.data = newData;
        this.capacity = newCapacity;
    }

既然扩容可以,当然也可以进行缩容:

 //删除操作
    public int removeByIndex(int index) {
        if (index < 0 || index >= this.size) {
            throw new IllegalArgumentException("index is invalid.");
        }
        //删除操作的核心
        /*
        1.找到删除的位置
        2.删除位置之后的元素要前移 arr[j-1]=arr[j]
         */
        T delValue = this.data[index];
        for (int i = index + 1; i < this.size; i++) {
            this.data[i - 1] = this.data[i];
        }
        this.size--;
        //判断是否缩容
        if (this.size < this.capacity / 2 && this.capacity / 2 > 0) {
            resize(this.capacity / 2);
        }
        return delValue;
    }

注意:这样缩容会出现一个问题:复杂度的震荡

复杂度震荡:

以本次的数组为例,在删除一定的元素,打到缩容的条件,进行缩容,但是下一步如果添加元素的话,又要进行扩容,时间复杂度就会增加,这就是复杂度的震荡

如何解决:

 //判断是否缩容
        if (this.size < this.capacity / 4 && this.capacity / 2 > 0) {
            resize(this.capacity / 2);
        }
        return delValue;
    }

缩容条件改为容积的1/4,这样留有空间进行添加元素,实在是不需要的情况下,再进行缩容。

处理多种类型的方法就是添加泛型:泛型 把类型当做参数文章来源地址https://www.toymoban.com/news/detail-800958.html

完整代码:

package com.algo.lesson.lesson01;

import java.util.Random;

/*
基于Java中的数组进行二次封装,制作一个可变数组
 */
//泛型:就是类型作为参数
public class MyArr<T> {
    private T[] data;//保存数据

    private int size;//数组中实际存放元素的个数

    int capacity;//容积

    //构造函数
    public MyArr(int capacity) {
        if (capacity <= 0) {
            this.capacity = 10;
        } else {
            this.capacity = capacity;
        }
        this.size = 0;
        this.data = (T[]) (new Object[this.capacity]);
    }

    //获取数组中实际存放元素的个数
    public int getSize() {
        return this.size;
    }

    //获取数组的容积
    public int getCapacity() {
        return this.capacity;
    }

    //判断数组是否为空
    public boolean isEmpty() {
        return this.size == 0;
    }

    //向数组中添加元素(尾部)
    public void add(T item) {
        //this.size 指向的是待插入元素的位置
        addInIndex(this.size, item);
    }

    //向数组中添加元素(头部)
    public void addHead(T item) {
        addInIndex(0, item);
    }

    //向数组中指定位置添加元素
    public void addInIndex(int index, T val) {
        if (index < 0 || index > this.size) {
            throw new IllegalArgumentException("index is invalid.");
        }
        //判断数组是否满
        if (this.size == this.capacity) {
            //扩容
            resize(this.capacity * 2);
        }
        //从index位置开始元素需要进行后移
        for (int i = this.size - 1; i >= index; i--) {
            this.data[i + 1] = this.data[i];
        }
        this.data[index] = val;
        //更新this.size
        this.size++;
    }

    private void resize(int newCapacity) {
        System.out.println("resize:" + newCapacity);
        T[] newData = (T[]) (new Object[newCapacity]);
        //将原数组驾到新数组里
        for (int i = 0; i < this.size; i++) {
            newData[i] = this.data[i];
        }
        //改变容器
        this.data = newData;
        this.capacity = newCapacity;
    }

    //修改指定位置的值
    public void modifyValueByIndex(int index, T value) {
        //入参一定要判断
        if (index < 0 || index >= this.size) {
            throw new IllegalArgumentException("index is invalid.");
        }
        this.data[index] = value;
    }

    //获取指定位置的值
    public T getValueByIndex(int index) {
        if (index < 0 || index >= this.size) {
            throw new IllegalArgumentException("index is invalid.");
        }
        return this.data[index];
    }

    //查询指定的值在数组中是否存在,如查存在,获取索引,否则返回-1
    public int containsValue(T val) {
        //遍历数组
        for (int i = 0; i < this.size; i++) {
            if (val.equals(this.data[i])) {
                return i;
            }
        }
        return -1;
    }

    //删除操作
    public T removeByIndex(int index) {
        if (index < 0 || index >= this.size) {
            throw new IllegalArgumentException("index is invalid.");
        }
        //删除操作的核心
        /*
        1.找到删除的位置
        2.删除位置之后的元素要前移 arr[j-1]=arr[j]
         */
        T delValue = this.data[index];
        for (int i = index + 1; i < this.size; i++) {
            this.data[i - 1] = this.data[i];
        }
        this.size--;
        //判断是否缩容
        if (this.size < this.capacity / 4 && this.capacity / 2 > 0) {
            resize(this.capacity / 2);
        }
        return delValue;
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder("[");
        for (int i = 0; i < this.size; i++) {
            sb.append(this.data[i]);
            if (i != this.size - 1) {
                sb.append(",");
            }
        }
        sb.append("]");
        return sb.toString();
    }

    public static void main(String[] args) {
        MyArr<Integer> myArr = new MyArr<>(10);
        Random random = new Random();
        //向数组中添加元素
        for (int i = 0; i < 10; i++) {
            myArr.add(random.nextInt(100));
        }
        //遍历数组
        System.out.println(myArr.toString());
        //查询
        //1.索引为2的位置值是多少
        int result = myArr.getValueByIndex(2);
        System.out.println("index=2,value=" + result);
        //2.获取值为57的元素的索引
        int index = myArr.containsValue(57);
        System.out.println("57元素的索引是" + index);
        //删除值为57的元素
        if (index != -1) {
            result = myArr.removeByIndex(index);
            System.out.println(result);
        }
        System.out.println(myArr);

        //向数组中指定位置添加元素(3,99)
        myArr.addInIndex(3, 99);
        System.out.println(myArr);

        /*
        1.向数组中继续添加一个元素,就会出错(解决方法:扩容)
        2.现在只能处理int类型,如何处理多种类型--(解决办法:泛型)
        3.删除元素后,空间利用率低--(解决办法:缩容)
         */

    }

}

到了这里,关于数据结构——用Java实现数组的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • 数据结构---数组(java)

    1 、数组基础 1 用来存储一组类型相同的数据 2 在内存中,分配连续的空间,数组创建时要指定容量(大小) 3 数据类型[] 数组名 int[] arr = new int[10] int[] arr2 = {1,2,3,4} 4 索引---访问数组时通过索引进行操作 5 索引从0开始,最大为 arr.length -1 6 常见的错误: NullPointException ArrayI

    2024年01月23日
    浏览(9)
  • Java 与数据结构(1):数组

    数组是一种线性数据结构,可以将一组相同类型的数据元素存储在顺序的连续内存空间中。每个元素都可以通过索引访问,索引通常从0开始。 在计算机内存中,数组的每个元素都占用相同的存储空间,这使得元素的访问变得更加高效,时间复杂度为O(1)。数组的长度一旦确定

    2024年02月04日
    浏览(9)
  • 数据结构Java版(1)——数组

    数据结构Java版(1)——数组

    是一门基础学科 研究的是数据如何在计算机中进行组织和存储,使得我们可以高效的获取数据和修改数据 数据结构可以分为三类: 线性结构: 数组、队列、栈、链表、哈希表… 树型结构:二叉树、二分搜索树、AVL树,红黑树、堆、Trie、线段树、并查集… 图结构:邻接矩阵

    2024年01月19日
    浏览(14)
  • 【数据结构】数组、双链表代码实现

    【数据结构】数组、双链表代码实现

    💗💗💗欢迎来到我的博客,你将找到有关如何使用技术解决问题的文章,也会找到某个技术的学习路线。无论你是何种职业,我都希望我的博客对你有所帮助。最后不要忘记订阅我的博客以获取最新文章,也欢迎在文章下方留下你的评论和反馈。我期待着与你分享知识、互

    2024年02月19日
    浏览(8)
  • 【数据结构—栈的实现(数组栈)】

    【数据结构—栈的实现(数组栈)】

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言 一、栈 1.1栈的概念及结构 二、栈的实现 2.1头文件的实现—Stack.h 2.2源文件的实现—Stack.c 2.3源文件的测试—test.c 三、栈的实际测试数据展示 3.1正常的出入栈展示: 3.2进栈同时也在出栈的

    2024年02月04日
    浏览(8)
  • 【数据结构】数组实现队列(详细版)

    【数据结构】数组实现队列(详细版)

    目录 队列的定义 普通顺序队列的劣势——与链队列相比  顺序队列实现方法: 一、动态增长队列  1、初始化队列  2、元素入队  3、判断队列是否为空  4、元素出队  5、获取队首元素 6、获取队尾元素  7、获取队列元素个数 8、销毁队列  总结: 动态增长队列完整测试代

    2024年04月28日
    浏览(11)
  • 用java以数组为底层数据结构创建自己的栈

    栈可以解决什么问题呢: 1.括号匹配问题 2.递归 3.表达式求值问题 首先明确栈的功能: 1.入栈:给底层数组的尾部插入元素相当于入栈 2.出栈:把底层数组的最后一个元素提出来相当于出栈 3.获取栈长度:获取size 4.判断栈是否为空:底层数组size==0则为空 5.获取栈顶:返回底层

    2024年01月20日
    浏览(11)
  • 数据结构:队列(链表和数组模拟实现)

    数据结构:队列(链表和数组模拟实现)

    目录 1.何为队列 2.链表模拟实现 2.1 节点和队列创建 2.2 初始化队列 2.3 入队操作 2.4 出队操作 2.5 遍历队列 2.6 获取队首和队尾元素 2.7 判断队列是否为空 2.8 完整实现 3. 数组模拟实现 3.1 创建队列 3.2 入队和出队操作 3.3 遍历队列 3.4 获取队首和队尾元素  3.5 判断队列是否为空

    2024年02月03日
    浏览(9)
  • 【数据结构和算法】使用数组的结构实现链表(单向或双向)

    【数据结构和算法】使用数组的结构实现链表(单向或双向)

    上文我们通过结构体的结构实现了队列 、以及循环队列的实现,我们或许在其他老师的教学中,只学到了用结构体的形式来实现链表、队列、栈等数据结构,本文我想告诉你的是,我们 可以使用数组的结构实现链表、单调栈、单调队列 目录 前言 一、用数组结构的好处 1.数

    2024年01月20日
    浏览(44)
  • 【数据结构】单链表 && 双链表(链式和数组实现)

    【数据结构】单链表 && 双链表(链式和数组实现)

           🔥🔥 欢迎来到小林的博客!!       🛰️博客主页:✈️小林爱敲代码       🛰️博客专栏:✈️ 数据结构与算法       🛰️社区 :✈️ 进步学堂       🛰️欢迎关注:👍点赞🙌收藏✍️留言 今天给大家带来四个内容,一个

    2024年02月01日
    浏览(40)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包