数据结构-数组

一,数组基础及注意事项

1,用来储存一组相同的类型的数据.
2,在内存中,分配连续的空姐,数组创建时要指定容量(大小).
3,创建格式: 数据类型 []数组名 int[] arr = new int[10] int[] arr2 = {1,2,3,4}.
4,索引--访问数组时通过索引进行操作.
(注意:一定要理解索引的含义,在数据结构的学习中基本每次都用,索引简单的可以理解为,待插入元素,即,还没有赋值的第一个元素.)
5.索引从0开始,最大为数组名.length-1;
6,常见的错误: NullPointException ArrayIndexOutOfBoundsException 即我们常说的空指针h=和越界.
7,常见的数组:字符串,对象数组,哈希表

二,演示数组的使用,及数组的方法使用

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

1,向数组中添加元素
2,向指定位置添加元素

3,向数组头添加元素
4,获取指定位置的元素和修改指定位置的元素
5,包含、搜索和删除元素

首先:对int类型的数组进行操作

接下来让我们手撕代码.:

复制代码
import java.util.Arrays;
import java.util.Random;

// 封装属于自己的数组
public class MyArray {
    private int[] data; // 底层数据结构
    private int size;// 用来保存实际存放元素的个数

    public MyArray() {
        this(100);
    }

    public MyArray(int capacity) {
        this.data = new int[capacity];
        this.size = 0;
    }

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

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

    // 对数组进行操作
    /*
    * 1、增加的方法
       发现:this.size指向待插入元素的位置,因此,可以在this.size位置增加元素
       在头部增加: 1》 将数组中的元素后移,2》 将val添加到索引为0的位置
       * 在任意位置添加
     */

    /**
     * 在尾部添加
     *
     * @param val val
     */
    public void addTail(int val) {
        add(this.size, val);
    }

    /**
     * 在头部添加
     *
     * @param val val
     */
    public void addHead(int val) {
        add(0, val);
    }

    /**
     * 在任意位置添加
     *
     * @param position 插入的位置
     * @param val      插入的值
     */
    public void add(int position, int val) {
        if (position < 0 || position > this.size) {
            throw new IllegalArgumentException("position is invalid");
        }
        for (int i = this.size - 1; i >= position; i--) {
            this.data[i + 1] = this.data[i];
        }
        this.data[position] = val;
        this.size += 1;
    }

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

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

    // 修改指定位置的元素
    public void setElementByIndex(int index, int val) {
        if (index < 0 || index >= this.size) {
            throw new IllegalArgumentException("index is invalid");
        }
        this.data[index] = val;
    }

    // cotains 用来判断数组中是否包含指定的元素
    public boolean contains(int searchVal) {
        for (int i = 0; i < this.size; i++) {
            if (this.data[i] == searchVal) {
                return true;
            }
        }
        return false;
    }

    // 查找指定元素在数组中的索引
    public int findIndex(int searchVal) {
        for (int i = 0; i < this.size; i++) {
            if (this.data[i] == searchVal) {
                return i;
            }
        }
        return -1;
    }

    // 删除数组中最后一个元素
    public int removeFromTail() {
        if (isEmpty()) {
            throw new IllegalArgumentException("this array is null!");
        }
        return this.data[--this.size];
    }

    // 删除数组中的第一个元素
    public int removeFromHead() {
        if (isEmpty()) {
            throw new IllegalArgumentException("this array is null!");
        }
        // 1、先保存数组中的第一个元素
        int result = this.data[0];

        // 2、将数组从索引为1的位置进行前移
        for (int i = 1; i < this.size; i++) {
            this.data[i - 1] = this.data[i];
        }
        this.size--;
        return result;
    }

    // 删除指定位置的元素
    public int removeByIndex(int index) {
        if (index < 0 || index >= this.size) {
            throw new IllegalArgumentException("index is invalid!");
        }
        int result = this.data[index];
        // 从索引为index位置的元素进行前移
        for (int i = index; i < this.size - 1; i++) {
            this.data[i] = this.data[i + 1];
        }
        this.size--;
        return result;
    }

    // 删除指定的元素
    public void remove(int val) {
        for (int i = 0; i < this.size; ) {
            if (this.data[i] == val) {
                // 删除元素---将后面的元素前移,然后更新size
                for (int j = i; j < this.size - 1; j++) {
                    this.data[j] = this.data[j + 1];
                }
                this.size -= 1;
            } else {
                i++;
            }
        }
    }

}

我们要进行任意数据类型的数组,这时就要使用泛型来进行操作.

接下来让我们手撕代码.在上述我们自己写的int类型数组进行修改,添加泛型.

复制代码
import java.util.Random;

// 封装属于自己的数组,使用泛型
public class MyArray2<T> {
    private T[] data; // 底层数据结构
    private int size;// 用来保存实际存放元素的个数

    private int capacity; // 表示容积

    public MyArray2() {
        this(100);
    }

    public MyArray2(int capacity) {
        this.capacity = capacity;
        this.data = (T[]) new Object[this.capacity];
        this.size = 0;
    }

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

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

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

    // 对数组进行操作
    /*
    * 1、增加的方法
       发现:this.size指向待插入元素的位置,因此,可以在this.size位置增加元素
       在头部增加: 1》 将数组中的元素后移,2》 将val添加到索引为0的位置
       * 在任意位置添加
     */

    /**
     * 在尾部添加
     *
     * @param val val
     */
    public void addTail(T val) {
        add(this.size, val);
    }

    /**
     * 在头部添加
     *
     * @param val val
     */
    public void addHead(T val) {
        add(0, val);
    }

    /**
     * 在任意位置添加
     *
     * @param position 插入的位置
     * @param val      插入的值
     */
    public void add(int position, T val) {
        if (position < 0 || position > this.size) {
            throw new IllegalArgumentException("position is invalid");
        }
        // 在增加之前,判断数组是否已满,如果已满,要进行扩容
        if (this.size == this.capacity) {
            // 扩容操作
            resize(this.capacity*2);
        }
        for (int i = this.size - 1; i >= position; i--) {
            this.data[i + 1] = this.data[i];
        }
        this.data[position] = val;
        this.size += 1;
    }

    // 改变容积的方法
    private void resize(int newCapacity) {
        System.out.println("--------resize--------");
        // 2、 创建一个新数组
        T[] newArr = (T[]) new Object[newCapacity];

        // 3、将原来数组的内容转移到新数组
        for (int i = 0; i < this.size; i++) {
            newArr[i] = this.data[i];
        }
        // 4、将newArr赋值给 this.data
        this.data = newArr;
        // 5、将newCapacity 赋值给this.capacity
        this.capacity = newCapacity;
    }

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

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

    // 修改指定位置的元素
    public void setElementByIndex(int index, T val) {
        if (index < 0 || index >= this.size) {
            throw new IllegalArgumentException("index is invalid");
        }
        this.data[index] = val;
    }

    // cotains 用来判断数组中是否包含指定的元素
    public boolean contains(T searchVal) {
        for (int i = 0; i < this.size; i++) {
            if (this.data[i].equals(searchVal)) {
                return true;
            }
        }
        return false;
    }

    // 查找指定元素在数组中的索引
    public int findIndex(T searchVal) {
        for (int i = 0; i < this.size; i++) {
            if (this.data[i].equals(searchVal)) {
                return i;
            }
        }
        return -1;
    }

    // 删除数组中最后一个元素
    public T removeFromTail() {
        return removeByIndex(this.size-1);
    }

    // 删除数组中的第一个元素
    public T removeFromHead() {
        return removeByIndex(0);
    }

    // 删除指定位置的元素
    public T removeByIndex(int index) {
        if (index < 0 || index >= this.size) {
            throw new IllegalArgumentException("index is invalid!");
        }
        T result = this.data[index];
        // 从索引为index位置的元素进行前移
        for (int i = index; i < this.size - 1; i++) {
            this.data[i] = this.data[i + 1];
        }
        this.size--;
        if(this.size <= this.capacity/2 && this.capacity/2>1){
            resize(this.capacity/2);
        }
        return result;
    }

    // 删除指定的元素
    public void remove(int val) {
        for (int i = 0; i < this.size; ) {
            if (this.data[i].equals(val)) {
                // 删除元素---将后面的元素前移,然后更新size
                for (int j = i; j < this.size - 1; j++) {
                    this.data[j] = this.data[j + 1];
                }
                this.size -= 1;
            } else {
                i++;
            }
        }
        // 删除之后,进行判断是否要进行缩容,如果需要缩容,缩到原容积的1/2
        if(this.size <= this.capacity/2 && this.capacity/2>1){
            resize(this.capacity/2);
        }
    }
}

代码较长希望有心人可以看完.

三,数组的复杂度分析.

我们对数组的逻辑有了简单的了解,就对数组的复杂度进行分析,后面可以通过比较复杂度,来选择合适的数据结构来储存数据.

1,分析动态数组的时间复杂度

(1),添加操作

1,addLast(e) O(n)

2,addFirst(e) O(1) 渐进时间复杂度

3,add(index,e) O(n^2) 描述n趋近于无穷的情况

(2),添加操作
(3),删除操作
(4),修改操作
(5),查找操作
(6) 综合
相关推荐
路在脚下@几秒前
Springboot 的Servlet Web 应用、响应式 Web 应用(Reactive)以及非 Web 应用(None)的特点和适用场景
java·spring boot·servlet
黑马师兄1 分钟前
SpringBoot
java·spring
数据小小爬虫25 分钟前
如何用Java爬虫“偷窥”淘宝商品类目API的返回值
java·爬虫·php
暮春二十四26 分钟前
关于用postman调用接口成功但是使用Java代码调用却失败的问题
java·测试工具·postman
java小吕布1 小时前
Java中Properties的使用详解
java·开发语言·后端
爱吃土豆的程序员1 小时前
在oracle官网下载资源显示400 Bad Request Request Header Or Cookie Too Large 解决办法
java·数据库·oracle·cookie
尚学教辅学习资料1 小时前
基于微信小程序的电商平台+LW示例参考
java·微信小程序·小程序·毕业设计·springboot·电商平台
尘浮生1 小时前
Java项目实战II基于微信小程序的移动学习平台的设计与实现(开发文档+数据库+源码)
java·开发语言·数据库·spring boot·学习·微信小程序·小程序
2401_857610032 小时前
Spring Boot框架:电商系统的技术优势
java·spring boot·后端
希忘auto2 小时前
详解MySQL安装
java·mysql