【js】-【数组、栈、队列、链表基础】-笔记

28 篇文章 0 订阅
14 篇文章 0 订阅

声明:本笔记是根据掘金小册总结的,如果要学习更多细节,请移步https://juejin.cn/book/6844733800300150797

1 数组

1.1 一维创建

const arr = []
const arr = new Array()

指定长度

const arr = new Array(7)

创建一个长度确定、同时每一个元素的值也都确定的数组

const arr = (new Array(7)).fill(1)

1.2 一维遍历

  1. for 循环
// 获取数组的长度
const len = arr.length
for(let i=0;i<len;i++) {
    // 输出数组的元素值,输出当前索引
    console.log(arr[i], i)
}
  1. forEach 方法
arr.forEach((item, index)=> {
    // 输出数组的元素值,输出当前索引
    console.log(item, index)
})
  1. map 方法

在遍历的基础上“再加工”

const newArr = arr.map((item, index)=> {
    // 输出数组的元素值,输出当前索引
    console.log(item, index)
    // 在当前元素值的基础上加1
    return item+1
})

map来返回了一个全新的数组,数组中每个元素的值都是在其现有元素值的基础上+1后的结果

1.3 二维数组

初始化一个二维数组

const len = arr.length
for(let i=0;i<len;i++) {
    // 将数组的每一个坑位初始化为数组
    arr[i] = []
}
let dp = Array.from(new Array(3), () => new Array(2).fill(1));
console.log(dp);
[[1, 1], [1, 1], [1, 1]]

1.4 二维数组遍历

# 缓存外部数组的长度
const outerLen = arr.length
for(let i=0;i<outerLen;i++) {
    #  缓存内部数组的长度
    const innerLen = arr[i].length
    for(let j=0;j<innerLen;j++) {
       # 输出数组的值,输出数组的索引`const arr = [1,2]
arr.push(3) // [1,2,3]`
        console.log(arr[i][j],i,j)
    }
}

2 数组增加与删除方法

2.1 数组中增加元素

  1. unshift 方法-添加元素到数组的头部
const arr = [1,2]
arr.unshift(0) # [0,1,2]
  1. push 方法-添加元素到数组的尾部
const arr = [1,2]
arr.push(3) # [1,2,3]
  1. splice 方法-添加元素到数组的任何位置
const arr = [1,2] 
arr.splice(1,0,3) # [1,3,2]
第一个入参是起始的索引值,第二个入参表示从起始索引开始需要删除的元素个数,第三个参数是传入值

2.2 数组中删除元素

  1. shift 方法-删除数组头部的元素
const arr = [1,2,3]
arr.shift() # [2,3]
  1. pop 方法-删除数组尾部的元素
const arr = [1,2,3]
arr.pop() # [1,2]
  1. splice 方法-删除数组任意位置的元素
const arr = [1,2,3]
arr.splice(1,1) # [1, 3]

3 栈、队列

栈和队列的实现一般都要依赖于数组
两者的区别在于,它们各自对数组的增删操作有着不一样的限制。

3.1 栈

只允许从尾部添加元素
只允许从尾部取出元素

// 初始状态,栈空
const stack = []  
// 入栈过程
stack.push('东北大板')
stack.push('可爱多')
stack.push('巧乐兹')
stack.push('冰工厂')
stack.push('光明奶砖')

// 出栈过程,栈不为空时才执行
while(stack.length) {
    // 单纯访问栈顶元素(不出栈)
    const top = stack[stack.length-1]
    console.log('现在取出的冰淇淋是', top)  
    // 将栈顶元素出栈
    stack.pop()
}

// 栈空
stack // []

3.2队列

只用 push 和 shift 完成增删的“数组”

const queue = []  
queue.push('小册一姐')
queue.push('小册二姐')
queue.push('小册三姐')  
  
while(queue.length) {
    // 单纯访问队头元素(不出队)
    const top = queue[0]
    console.log(top,'取餐')
    // 将队头元素出队
    queue.shift()
}

// 队空
queue // []

4 链表

链表中,数据单位的名称叫做“结点”,而结点和结点的分布,在内存中可以是离散的。
要想访问链表中的任何一个元素,我们都得从起点结点开始,逐个访问 next,一直访问到目标结点为止。为了确保起点结点是可抵达的,我们有时还会设定一个 head 指针来专门指向链表的开始位置:在这里插入图片描述

  1. 创建链表结点,需要一个构造函数:
function ListNode(val) {
    this.val = val;
    this.next = null;
}
  1. 使用构造函数创建结点
const node = new ListNode(1)  
node.next = new ListNode(2)

数据域值为1,next 结点数据域值为2
在这里插入图片描述
3. 任意两结点间插入一个新结点

我们需要变更的是前驱结点目标结点的 next 指针指向
在这里插入图片描述

# 如果目标结点本来不存在,那么记得手动创建
const node3 = new ListNode(3)     

# 把node3的 next 指针指向 node2(即 node1.next)
node3.next = node1.next

# 把node1的 next 指针指向 node3
node1.next = node3
  1. 链表元素的删除

直接让它的前驱结点 node1 的 next 指针跳过它、指向 node3 的后继在这里插入图片描述

node1.next = node3.next 

可以只使用一个指针,这个指针用来定位目标结点的前驱结点。

// 利用 node1 可以定位到 node3
const target = node1.next  
node1.next = target.next

相对于数组来说,链表有一个明显的优点,就是添加和删除元素都不需要挪动多余的元素

在链表中,只要明确了要插入/删除的目标位置,增删操作的复杂度是常数级别的复杂度,表示为 O(1)。

但是链表也有一个弊端:当我们试图读取某一个特定(第i个)的链表结点时,必须遍历整个链表来查找它,表示为 O(n)。
但在数组中,我们直接访问索引、可以做到一步到位,这个操作的复杂度会被降级为常数级别O(1)

链表的插入/删除效率较高,而访问效率较低;数组的访问效率较高,而插入效率较低

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值