数组和链表的区别
1、前言
当遇到要存储多个元素的过程中,数组可能是最常用的数据结构
数组的创建通常需要申请一段连续的内存空间(一整块的内存) 并且大小是固定的(大多数编程语言数组都是固定的) 。
所以当当前数组不能满足容量需求时,需要扩容 (一般情况下是申请一个更大的数组,比如2倍.然后将原数组中的元素复制过去)
而且在数组开头或中间位置插入数据的成本很高,需要进行大量元素的位移。
尽管我们已经学过的JavaScript的Array类方法可以帮我们做这些事,但背后的原理依然是这样。
2、链表与数组对比
链表和数组一样,可以用于存储一系列的元素,但是链表和数组的实现机制完全不同。
要存储多个元素,另外一个选择就是链表
但不同于数组,链表中的元素在内存中不必是连续的空间
链表的每个元素由一个存储元素本身的节点和一个指向下一个元素的引用(有些语言称为指针或者连接)组成
内存空间不是必须连续的. 可以充分利用计算机的内存.实现灵活的内存动态管理。
链表不必在创建时就确定大小, 并且大小可以无限的延伸下去。
链表在插入和删除数据时,时间复杂度可以达到O(1).相对数组效率高很多。
3、特点:
只能从头遍历到尾或者从尾遍历到头(一般从头到尾)
也就是链表相连的过程是单向的。
实现的原理是上一个结点中有一个指向下一个是引用单向链表比较明显的缺点。
图片展示
代码展示
class Node{
constructor(element){
this.element = element;
this.next = null
}
}
class LinkedList{
constructor(){
this.head = null;
this.length = 0
}
// 新增在链表尾部添加一个新的项
append(element){
const newNode = new Node(element);
if(!this.head){
this.head = newNode;
}else{
let current = this.head;
while(current.next){
current = current.next
}
current.next = newNode;
}
this.length++
}
// 向链表特定位置插入一个新的项
insert(position,element){
if(position < 0 || position > this.length) return false;
const newNode = new Node(element);
//插入元素
if(position == 0){
newNode.next = this.head;
this.head = newNode
}else{
let index = 0;
let current = this.head;
let previous = null;
while(index++ < position){
previous = current;
current = current.next
}
previous.next = newNode;
newNode.next = current;
}
this.length++
return true
}
// 读取相对应位置元素
get(position) {
// 判断越界问题
if (position < 0 || position > this.length - 1) return false
let index = 0
let current = this.head;
while (index++ < position) {
current = current.next
}
return current.element
}
// 返回元素在链表中的索引,如果列表中没有返回-1
indexOf(element) {
let index = 0
let current = this.head;
while (current.next) {
if (current.element == element) {
return index
}
index++;
current = current.next
}
return -1
}
// 修改某个位置的元素
update(position, element) {
if (position < 0 || position > this.length) return false
this.removeAt(position);
this.insert(position, element);
}
// 从链表的特定位置移除一项
removeAt(position) {
if (position < 0 || position > this.length - 1) return null;
let index = 0
let current = this.head;
let previous = null
if (position === 0) {
this.get = current.next
} else {
while (index++ < position) {
previous = current;
current = current.next
}
previous.next = current.next;
}
this.length--;
}
// 从链表中移除一项
remove(element) {
const index = this.indexOf(element);
if (index == -1) return
this.removeAt(index)
}
// 如果链表中不包含任何元素返回true,否则false
isEmpty() {
if (this.length == 0) {
return true
} else {
return false
}
}
// 返回链表中元素的个数,鱼数组属性类似
size() {
return this.length
}
}