美文网首页
数据结构-数组

数据结构-数组

作者: acc8226 | 来源:发表于2021-05-28 22:11 被阅读0次

    数组(Array)是一种线性表数据结构。它用一组连续的内存空间,来存储一组具有相同类型的数据。

    这个定义里有几个关键词,理解了这几个关键词,我想你就能彻底掌握数组的概念了。下面就从我的角度分别给你“点拨”一下。

    第一是线性表(Linear List)。顾名思义,线性表就是数据排成像一条线一样的结构。每个线性表上的数据最多只有前和后两个方向。其实除了数组,链表、队列、栈等也是线性表结构。而与它相对立的概念是非线性表,比如二叉树、堆、图等。之所以叫非线性,是因为,在非线性表中,数据之间并不是简单的前后关系。

    第二个是连续的内存空间和相同类型的数据。正是因为这两个限制,它才有了一个堪称“杀手锏”的特性:“随机访问”。但有利就有弊,这两个限制也让数组的很多操作变得非常低效,比如要想在数组中删除、插入一个数据,为了保证连续性,就需要做大量的数据搬移工作。

    我们知道,计算机会给每个内存单元分配一个地址,计算机通过地址来访问内存中的数据。当计算机需要随机访问数组中的某个元素时,它会首先通过下面的寻址公式,计算出该元素存储的内存地址:

    a[i]_address = base_address + i * data_type_size
    

    其中 data_type_size 表示数组中每个元素的大小。我们举的这个例子里,数组中存储的是 int 类型数据,所以 data_type_size 就为 4 个字节。这个公式非常简单,我就不多做解释了。

    这里我要特别纠正一个“错误”。我在面试的时候,常常会问数组和链表的区别,很多人都回答说,“链表适合插入、删除,时间复杂度 O(1);数组适合查找,查找时间复杂度为 O(1)”。

    实际上,这种表述是不准确的。数组是适合查找操作,但是查找的时间复杂度并不为 O(1)。即便是排好序的数组,你用二分查找,时间复杂度也是 O(logn)。所以,正确的表述应该是,数组支持随机访问,根据下标随机访问的时间复杂度为 O(1)。

    容器能否完全替代数组?

    1. Java ArrayList 无法存储基本类型,比如 int、long,需要封装为 Integer、Long 类,而 Autoboxing、Unboxing 则有一定的性能消耗,所以如果特别关注性能,或者希望使用基本类型,就可以选用数组。

    2. 如果数据大小事先已知,并且对数据的操作非常简单,用不到 ArrayList 提供的大部分方法,也可以直接使用数组。

    3. 还有一个是我个人的喜好,当要表示多维数组时,用数组往往会更加直观。比如 Object[][] array;而用容器的话则需要这样定义:List<ArrayList<object>> array。

    内容小结

    我们今天学习了数组。它可以说是最基础、最简单的数据结构了。数组用一块连续的内存空间,来存储相同类型的一组数据,最大的特点就是支持随机访问,但插入、删除操作也因此变得比较低效,平均情况时间复杂度为 O(n)。在平时的业务开发中,我们可以直接使用编程语言提供的容器类,但是,如果是特别底层的开发,直接使用数组可能会更合适。

    必练操作

    接口定义

    package com.s1.array;
    
    public interface IList {
    
        void print();
    
        // 往尾部添加
        void add(Integer data);
    
        void addFirst(Integer data);
    
        void addLast(Integer data);
    
        // 指定位置添加元素(有效范围内)
        void add(int position, Integer data);
        
        // 往尾部删除
        Object remove();
    
        // 删除首元素
        Object removeFirst();
    
        // 删除尾元素
        Object removeLast();
    
        // 删除指定下标的元素
        Object remove(int index);
        
        // 删除指定数据的元素
        Object remove(Object obj);  
            
        // 改1 : 找到下标,然后更改
        boolean updateByPosition(int position, Integer value);
        
        // 改2 : 找到原数据,然后更改
        boolean updateByData(Integer oldData, Integer newData);
        
        void clear();   
    }
    
    • 实现一个支持动态扩容的数组
    • 实现一个大小固定的有序数组,支持动态增删改操作
    • 实现两个有序数组合并为一个有序数组

    我的代码
    https://gitee.com/kaiLee/struct/tree/master/src/main/java/com/s1

    参考

    05 | 数组:为什么很多编程语言中数组都从0开始编号? https://time.geekbang.org/column/article/40961

    java/05_array · 编程语言算法集/algo - 码云 - 开源中国 https://gitee.com/TheAlgorithms/algo/tree/master/java/05_array

    相关文章

      网友评论

          本文标题:数据结构-数组

          本文链接:https://www.haomeiwen.com/subject/gbbzjltx.html