数组

  1. 数组是一种线性的结构
  2. 在数据中的内存地址是连续的,这也就是在数组中为什么要指定数组的大小,只有在连续空间内数组才能成立。
  3. 在一个数组里面存储的数据结构都是相同的

数组的特点

下图是int[] a = new int[10] 数组结构。在下图可以看到数组的内存地址都是连续的。由于int 在Java占用4个字节。可以看到 每个空间都占用4个字节。

java 连续整数数组 java数组空间是否连续_为什么数组的下标为0

当数组进行插入操作时,需要将插入位置的元素整体向后移动一位,int[3] 到**int[6] **的位置都要像后面移动一位,所以说数组在进行插入操作时是比较耗时的。当数组需要在第一位插入元素时,数组的需要整体向后移动,时间复制度就会变成O(n),当数组在最后一位时数组的时间复制度就是O(1),所以数组的评价时间复制度位O(n/2),也是就是O(N)

java 连续整数数组 java数组空间是否连续_数组_02

当数组需要删除操作时,也需要进行数据数据的移动,时间时间复制度也是O(n)

java 连续整数数组 java数组空间是否连续_java_03

在Java中ArrayList 也是通过数组实现的,ArrayList最大的优势就是将很多数组的操作的细节封装起来和动态扩容。

在使用ArrayList时如果可以需要使用的大小可以给ArrayList设置初始值,省掉很多次内存申请和数据搬移操作,避免在扩容时消耗掉部分性能。

数组的基本操作

public class ArraysTest {
    private int size;
    private int[] data;
    private int index; //当前以存的数据大小

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


    public void print(){
        for (int i = 0; i < size  ; i++) {
            System.out.printf(data[i]+" ");
        }
    }
    //插入元素
    public  void insert(int loc,int n){
        if (index++ < size){
            for (int i = size -1; i > loc ; i--) {
                data[i] = data[i-1];
            }
            data[loc] = n;
        }
    }

    public void delete(int loc){   //O(n)
        for(int i = loc ; i < size ; i++){
            if(i != size - 1){    //怕越界所以加一个判断
                data[i] = data[i + 1];
            }else{
                data[i] = 0;         //默认为0 就是没存数据的
            }
        }
        index -- ;
    }
    public void update(int loc,int n){
        data[loc] = n;
    }
    public int get(int loc){
        return data[loc];
    }
  }

为什么大部分的数组的起始位是0

在数组存储的内存模型上可以看到,数组的 下标 最准确的定义应该是 偏移(offset)。如果用a来表示数组的首先地址,a[0]的偏移位置为0的位置,也是a[k]表示偏移k个 type_size 的位置,在计算a[k]的内存地址只需要使用这个公式:

a[k] _address = base_address + k * type_size

如果数组是从1开始,那么a[k]的计算方式就是

a[k] _address = base_address + (k -1)* type_size

当每次进行访问时,数组元素就会多了一次减法运算,对于cpu来说,就是多了一次减法运算。

C 语言设计使用0作为数组的下标,在之后其他语言都模仿了C 语言,在设计上就可以减低学习成本。