数据结构与算法第二章:数组

数据结构与算法

第一章:二分查找
第二章:数组



前言

随着计算机行业的发展,出现了许许多多的数据结构,我们今天来了解一下最基础的数据结构


提示:以下是本篇文章正文内容,下面案例可供参考

一、数组是什么?

数组(Array)是一种线性数据结构,用于存储相同类型的元素集合。它是一种有序的数据结构,可以通过==索引(下标)==来访问和操作其中的元素。数组是计算机科学中最基本、最常见的数据结构之一,被广泛应用于编程语言和算法中。
特点
1、有序集合: 数组中的元素按顺序存储,并通过数字索引访问。索引从0开始,用于唯一标识数组中的每个元素。
2、相同类型元素: 数组中的元素类型必须相同(整数、浮点数、字符等),这意味着数组是同质的。
3、固定大小: 大多数编程语言中的数组具有固定的长度,一旦创建,其大小通常无法改变。
4、连续存储: 数组中的元素在内存中是连续存储的,这也是它能够通过索引快速访问元素的原因。
空间占用:
Java 中数组结构上是这样的:

  • 8字节 markword
  • 4字节 class 指针(压缩 class 指针的情况)
  • 4 字节数组大小(决定了数组最大容量为232
  • 数组元素 + 对齐字节(Java 中所有对象大小都是 8 字节的整数倍,不足的要用字节补齐)

随机访问:即根据索引查找元素,在找到索引的前提下,时间复杂度为O(1) ,查找的快慢与数据规模没关系。

二、动态数组

1.数组的操作

import java.util.Arrays;
import java.util.Iterator;
import java.util.function.Consumer;
import java.util.stream.IntStream;

//	动态数组实现类
public class DynamicArray implements Iterable<Integer>{
    private int size = 0;   // 逻辑大小
    private int capacity = 8;   // 容量
    private int[] array = {};
    public void addLast(int element){
//        array[size] = element;
//        size++;
        add(size, element);
    }

	//添加元素
    public void add(int index,int element){
        checkAndGrow();
        if(index >= 0 && index < size) {
            System.arraycopy(array, index, array, index + 1, size - index);
        }
        array[index] = element;
        size++;
    }

	//检查容量
    private void checkAndGrow() {
        if(size == 0){
            array = new int[capacity];
        } else if(size == capacity){//检查容量
            capacity += capacity >> 1;
            //扩容到1.5倍
            int[] newArray = new int[capacity];
            System.arraycopy(array,0,newArray,0,size);
            array = newArray;
        }
    }

	//根据下标获取元素
    public int get(int index) {
        return array[index];
    }

    //遍历方法一
    //遍历要执行的操作,传入参数每个元素
    public void forI(Consumer<Integer> consumer) {
        for (int i:array) {
            consumer.accept(i);
        }
    }

    //遍历方法二
    //迭代器遍历
    @Override
    public Iterator<Integer> iterator() {
        return new Iterator<Integer>() {
            int i = 0;
            @Override
            public boolean hasNext() {//遍历过程中有没有下一个元素,有返回 true,没有返回 false
                return i < size;
            }

            @Override
            public Integer next() {// 返回当前元素,并移动到下一个元素
                return array[i++];
            }
        };
    }

    //遍历方法三
    //用Stream流来遍历
    public IntStream stream() {
        return IntStream.of(Arrays.copyOfRange(array,0,size));
    }

    //删除元素
    public int remove(int index) {
        int removed = array[index];
        if (index < size - 1) {
            System.arraycopy(array, index + 1, array, index, size - index - 1);
        }
        size--;
        return removed;
    }
}

2.二维数组

储存格式

int[][] array = {
	{11, 12, 13, 14, 15},
	{21, 22, 23, 24, 25},
	{31, 32, 33, 34, 35},
};

内存分布图

  • 外面的二维数组占 32 个字节,其中[0] , [1] , [2]分别保存了指向三个一维数组的引用
  • 三个一维数组各占 40 个字节
  • 它们在内存布局上是连续
    我们可以通过数组名来访问到二维数组的每一个元素,例如:array[1][1]就可以访问到下标为一的行中下标为1的元素。所以array[i][j]i 表示的是行的索引,j 表示的是列的索引。

二维数组的遍历:
有两种方式来遍历二维数组,分别是先遍历行在遍历列和先遍历列再遍历行,那么这两种情况下哪种情况的运行时间更短呢?
结论是先遍历行的运行速度更块,那么原因是什么呢?接下来我会为大家介绍原因:

原因就是局部性原理:

  • 时间局部性(Temporal Locality): 如果在一段时间内访问了某个数据,那么在不久的将来,很可能会再次访问同一数据。这意味着,最近访问过的数据很可能在近期内会再次被访问到。这种现象是因为程序在执行时倾向于重复使用相同的数据项或指令。

  • 空间局部性(Spatial Locality): 如果在某个时间点上访问了某个数据,那么在接下来的一段时间内,很可能会访问其附近的数据。这意味着,一旦访问了某个数据项,附近的数据项也可能被访问到。这种现象是因为程序在执行时往往按照连续的内存位置访问数据,比如数组、相邻的数据结构等。

内存中的数据以块的形式被加载到CPU的缓存中,先遍历行再遍历列可以利用内存的局部性原理,即空间局部性。行优先遍历意味着连续的元素在内存中是相邻的,这样一次缓存加载可以获取多个连续的元素,减少了内存访问次数,提高了缓存的命中率。而先遍历列则会破坏内存的局部性,导致缓存不命中率增加。CPU缓存会根据数据的访问模式进行预取(prefetching),如果连续的数据被访问,CPU缓存更容易预测下一个数据,从而提高访问速度。行优先遍历更有利于CPU缓存的预取机制。


总结

以上就是本篇文章主要的内容,本篇文章为大家介绍了最基础的数据结构——数组,读完了本篇文章,相信大家对于数组已经有了自己的了解,能够再平常对数组的使用中更加熟练。如果大家有什么问题可以提出来,欢迎大家提出相关的建议。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值