数据结构之数组

数组是有限个相同类型的变量所组成的有序集合,数组中的每一个变量被称为元素。数组是最简单、最常用的数据结构。以整型数组为例,数组的存储形式为:

数组中每一个元素都有自己的下标,这个下标从 0 开始,一直到数组长度 - 1 结束。数组的另外一个特点就是在内存中顺序存储,所以可以很好地实现逻辑上的顺序表。那顺序存储是个什么样子呢?我们知道,内存是由一个个连续的内存单元组成的,每一个内存单元都有自己的地址。在这些内存单元中,有些被其他数据占用了,有些是空闲的。数组中的每一个元素都存储在小小的单元中,并且元素之间紧密排列,既不能打乱元素的存储顺序,也不能跳过每个存储单元存储。

如上图所示,连续的 8 个红色的单元我们用来存储数组,绿色的单元表示空闲的单元,数组在存储时必须是连续的,不能在内存中随意去占领空闲的单元。

数组的基本操作:

1.读取元素:对于数组来说,读取元素是最简单的操作。由于数组在内存中顺序存储,所以只需要给出一个数组的下标,就可以读取到对应的数组元素。假设有一个名称为 array 的数组,我们需要读取下标为 3 的元素,就可以写作 array[3]。需要注意的是,输入的下标必须在数组的长度范围之内,否则会出现数组越界的情况。像这种根据下标读取元素的方式叫作随机读取。时间复杂度为 O(1)

2.更新元素:要把数组中的某一元素的值替换为另一个新值,也是常见的数组操作。直接利用下标把新值赋值给该元素即可。时间复杂度为 O(1)

3.插入元素:由于需要考虑到数组的实际数量有可能小于数组的长度,所以插入数组元素存在三种情况,即尾部插入、中间插入和超范围插入。

尾部插入是最简单的情况,即直接把插入的元素放在数组尾部的空闲位置,等同于更新操作;中间插入的操作稍微复杂一点。由于数组中每一个元素都有其固定的下标,所以不得不首先把插入位置及后面的元素向后移动,为要插入的元素腾出地方,然后再把要插入的元素放到对应的数组位置上。那么超范围插入又是一种什么情况呢?假设不断地往数组中插入新元素,直到元素数量超过数组的最大长度时,便引出了数组的超范围插入的操作。也就是说,如果有一个长度为 6 的数组,现在已经装满了元素,这是如果还想插入一个元素的话就属于超范围插入。这时就涉及到数组的扩容,但是数组的长度在数组创建时就已经确定了,不能随意扩容或缩短。此时我们可以创建一个新的数组,长度是旧数组的两倍,再把旧数组中的元素统统复制到新数组中,这样就实现了数组的扩容。插入元素的时间复杂度为 O(n),因为涉及到数组元素的移动。

4.删除元素:数组的删除操作和插入过程相反,如果删除的元素位于数组中间,其后的元素都需要向前移动一位。时间复杂度是 O(n)

相关的代码实现如下:

public class ArrayTest {

    // 打印数组
    public static void display(int[] array) {
        System.out.print("数组中元素为:");
        for (int i = 0; i < array.length - 1; i++) {
            if (array[i] != 0) {
                System.out.print(array[i] + "-->");
            }
        }
        System.out.println(array[array.length - 1]);
    }

    /**
     * @param array 数组
     * @param index 下标,默认下标有效,所以不做对下标的额外处理
     * 读取数组元素
     */
    public static void readElement(int[] array, int index) {
        // 默认输入的 index 是有效的,所以不做额外的处理
        System.out.println("数组中下标为" + index + "的元素为:" + array[index]);
    }

    /**
     * @param array 数组
     * @param index 要更新元素的下标,默认有效
     * @param element 要更新的新值
     * 更新数组元素
     */
    public static void updateElement(int[] array, int index, int element) {
        System.out.println("更新下标为" + index + "的元素为:" + element);
        array[index] = element;
    }

    /**
     * @param array 数组
     * @param index 插入元素的位置
     * @param element 插入元素
     * 往数组中插入元素
     */
    public static int[] insertElement(int[] array, int index, int element) {
        int size = array.length;
        // 判断插入位置是否合法
        if (index < 0 || index >= size - 1) {
            System.out.println("插入位置非法!");
            return array;
        }
        // 如果数组实际元素达到数组容量上限,则扩容,测试时该条件恒为 true
        int[] newArray = new int[array.length * 2];
        if (size >= array.length) {
            // 复制 array 到 newArray 中
            System.arraycopy(array, 0, newArray, 0, array.length);
        }
        // 从右向左循环,将元素逐个向右挪一位
        for (int i = array.length - 1; i >= index; i--) {
            newArray[i + 1] = newArray[i];
        }
        // 腾出来的位置插入 element
        newArray[index] = element;
        return newArray;
    }

    /**
     * @param array 数组
     * @param index 要删除的下标,默认有效
     * 删除数组元素
     */
    public static void deleteElement(int[] array, int index) {
        // 将 index 之后的元素向前移动一位
        for (int i = index; i < array.length - 1; i++) {
            array[i] = array[i + 1];
        }
        // 为数组最后一位赋值为 0,占位
        array[array.length - 1] = 0;
    }

    public static void main(String[] args) {
        int[] array = new int[]{3, 1, 2, 5, 4, 9, 7, 2};
        display(array);
        readElement(array, 3);
        updateElement(array, 3, 10);
        display(array);
        int[] newArray = insertElement(array, 3, 20);
        display(newArray);
        deleteElement(array, 3);
        display(array);
    }

}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值