图解数据结构:数组和单链表

前言

数据结构始终是计算机科学绕不开的话题,是计算机中存储、组织数据的方式。学习数据结构能让我们明白,如何更高效的存、取数据。编写程序的目的就是为了处理数据,处理数据本质上就是存、取、运算。
本篇从最简单的数据结构入手,讲解数组和链表。主要讲解他们的特点、存储结构、区别、各种场景下的效率等问题。

数组

在计算机科学中,数组数据结构(英语:array data structure),简称数组(英语:Array),是由相同类型的元素(element)的集合所组成的数据结构,分配一块连续的内存来存储。利用元素的索引(index)可以计算出该元素对应的存储地址。

数组可以说是最常见的数据结构之一了,主要特点是

  • 能存储一系列相同类型的元素
  • 所有元素用一块连续的内存来存储
  • 利用元素的索引可以直接访问对应的数据
  • 数组是静态结构,初始化必须指定容量,且容量不变
Object[] arr = new Object[10];

是最常见定义数组的方式,如果要访问索引为1的数据,直接通过arr[1]即可访问。也就是说数组支持随机访问(RandomAccess)。第一次听到“随机访问”这个词的时候非常懵逼:既然是随机,那就表示不确定,也就是说没人知道程序会访问哪个数据,那怎么保证访问的就是程序需要的数据呢?后来才知道:这个随机访问(RandomAccess)倒不如翻译成“任意访问”,就是想访问哪个数据,就可以直接访问。数组就是这样,只需要给定下标就可以直接访问。

说数组是静态结构,容量不能变。可能有同学不理解了,ArrayList底层就是数组,但是ArrayList是可以自动扩容的。既然这样,那我就用数组手动实现简易版的ArrayList吧,简易的实现了ArrayList的核心功能,先来看下定义

/**
 * 动态数组实现ArrayList
 */
public class ArrayList<E> {

    /**
     * 默认容量
     */
    private static final int DEFAULT_CAPACITY = 10;
    /**
     * 扩容倍数
     */
    private static final int RESIZE_RATE = 2;

    private E[] table;
    private int size;
    
}

E[] table用来保存添加的元素,int size用来记录ArrayList中元素的个数。需要注意的是,size和容量并不一定相等,容量是table.length,也就是数组长度。

再来看两个核心方法add(...)remove()的实现思想,首先看下add(...)方法,往指定的位置插入元素,插入过程如下
数组指定位置插入
动画演示的是:把元素6插入下标为3的位置。在插入之前,必须先把下标3及以后的元素向后移动一格。并且必须按照下标递减的顺序来先后移动元素,避免元素被覆盖。
从图中便可以看出,向数组中间插入元素,时间复杂度是O(n),因为需要移动元素。但是向数组尾部插入元素,便不需要移动元素,所以时间复杂度为O(1)。由于向数组尾部插入元素有可能导致扩容操作(下面详细介绍),而扩容操作的时间复杂度为O(n),所以向数组尾部插入元素的最坏时间复杂度为O(n)。下面的代码是该逻辑的实现。

/**
 * 指定位置新增
 * @param index 下标
 * @param e 新增元素
 * @return 是否成功
 */
public boolean add(int index, E e) {
    if (index < 0 || index > size) {
     
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值