一、什么是数组
1、初识数组
数组对应的英文是array,是有限个相同类型的变量所组成的有序集合,数组中的每一个变量被称为元素。数组是最为简单、最为常用的数据结构。
数组中的每一个元素也有着自己的下标,只不过这个下标从0开始,一直到数组长度-1。
数组的另一个特点,是在内存中顺序存储,因此可以很好地实现逻辑上的顺序表。
2、数组的基本操作
1.读取元素
对于数组来说,读取元素是最简单的操作。由于数组在内存中顺序存储,所以只要给出一个数组下标,就可以读取到对应的数组元素。 array[1]
需要注意的是,输入的下标必须在数组的长度范围之内,否则会出现数组越界。
像这种根据下标读取元素的方式叫作随机读取。
时间复杂度是O(1)
2.更新元素
要把数组中某一个元素的值替换为一个新值,也是非常简单的操作。直接利用数组下标,就可以把新值赋给该元素。
时间复杂度是O(1)
3.插入元素
在介绍插入数组元素的操作之前,我们需要补充一个概念,那就是数组的实际元素数量有可能小于数组的长度
插入数组元素的操作存在3种情况。
尾部插入:尾部插入,是最简单的情况,直接把插入的元素放在数组尾部的空闲位置即可,等同于更新元素的操作。
中间插入:中间插入,稍微复杂一些。由于数组的每一个元素都有其固定下标,所以不得不首先把插入位置及后面的元素向后移动,腾出地方,再把要插入的元素放到对应的数组位置上。
超范围插入:如果一个数组已经装满元素这时还想插入一个新元素。这就涉及数组的扩容了。可是数组的长度在创建时就已经确定了,无法像孙悟空的金箍棒那样随意变长或变短。这该如何是好呢?此时可以创建一个新数组,长度是旧数组的2倍,再把旧数组中的元素统统复制过去,这样就实现了数组的扩容。
数组扩容的时间复杂度是O(n),插入并移动元素的时间复杂度也是O(n),综合起来插入操作的时间复杂度是O(n)
4.删除元素
数组的删除操作和插入操作的过程相反,如果删除的元素位于数组中间,其后的元素都需要向前挪动1位。
删除操作,只涉及元素的移动,时间复杂度也是O(n)。
3、数组的优势和劣势
数组拥有非常高效的随机访问能力,只要给出下标,就可以用常量时间找到对应元素。有一种高效查找元素的算法叫作二分查找,就是利用了数组的这个优势。
至于数组的劣势,体现在插入和删除元素方面。由于数组元素连续紧密地存储在内存中,插入、删除元素都会导致大量元素被迫移动,影响效率。
二、什么是链表
链表(linked list)是一种在物理上非连续、非顺序的数据结构,由若干节点(node)所组成。
1、单向链表
单向链表的每一个节点又包含两部分,一部分是存放数据的变量data,另一部分是指向下一个节点的指针next。
链表的第1个节点被称为头节点,最后1个节点被称为尾节点,尾节点的next指针指向空。
与数组按照下标来随机寻找元素不同,对于链表的其中一个节点A,我们只能根据节点A的next指针来找到该节点的下一个节点B,再根据节点B的next指针找到下一个节点C……
2、双向链表