高冷数组难接近 傲娇链表求抱抱

321 阅读4分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第17天,点击查看活动详情

目录

今日题

  1. 题目
  2. 分析 昨日题
  3. 题目
  4. 答案
  5. 解析 结语

今日题

题目

今天先谈一谈数组这种结构,它里面所有的成员都是按照顺序来进行存储的,在这个数组中第一个成员的地址加上自身的字节数等于数组第二个成员的地址,并以此类推

基地址 + 元素大小 * k 3.png

正是由于这种机制的存在,所以数组在执行查找操作时,速度很快,因为数组的时间复杂度为O(1);但是插入和删除都很费时间,如图所示:

1.png

如果删除①,则② ~ ⑤都要往前移,如果在① ~ ②之间插入一个元素,则② ~ ⑤都要往后移,而如果是在④ ~ ⑤之间插入/删除,则只需要移动⑤即可,也就是说,如果操作数组前面的元素,还是比较费时的

如果要在⑤后面再添加一个元素,则应该使用一个大的数组,然后把原数组复制进去:

2.png

由此可见数组在增删的过程中,耗能十分严重。那有没有弥补了这个缺点的数据结构呢? 肯定是有的,下面有请我们今天的主角——链表

若无特殊说明,本文章中所有链表均以单向链表为例

链表的基本思想大概是,利用对象的特点,额外开辟出一份内存空间去作指针,它总是指向下一个结点,一个个结点通过NEXT指针相互串联,这样的数据结构我们就称它为链表。说人话就是,链表的每一个结点都存储着两个值,一个是本身的数据,另一个则指向了下一个结点。并且链表因为自身靠指针维系,所以增删的耗能都非常的小。

例如,将以上链表的第二位删除,我们只需要将1存储的指针指向3的地址就可以了。存储着2的结点会被gc自动回收。了解了链表的优势以及特点之后,我们就可以封装自己的函数,用来将数组转换为链表了。

分析

首先每个结点有两个属性valuenext,其中value代表当前结点的值,next永远指向下个结点,要注意尾结点的next应为null。假设有A、B、C三个结点,现在想删除B结点,则应该让A结点的next指向C结点,然后将B结点置为null,如果想增加结点D,则应让Cnext指向D。这种数据结构的缺点就是查找慢,因为是线性查找,但在增、删时效率是要比数组高的

昨日题

题目

用原生的JavaScript封装一个用户的构造函数(可被 new 的函数), 该函数可传入一个配置对象

// 配置对象 具体信息自己决定
{
    name: "张三",
    age: "18",
    sex: "男"
}

在返回的实例上有一个说话的方法say() 该方法可传入一串任意长度的字符串 比如: say("法外狂徒") 调用该方法后控制输出 : 张三 (男 - 18岁): 法外狂徒

答案

无固定答案,下面仅展示部分写法:

function Constructor(obj){
  this.name=obj.name
  this.age=obj.age
  this.sex=obj.sex
}
Constructor.prototype.say=function(str){
    console.log(`${this.name}${this.sex}-${this.age}):${str}`)
}
let obj=new Constructor({
    name: "张三",
    age: "18",
    sex: "男"
})
obj.say("法外狂徒")

解析

  1. js中使用new关键字调用函数分四步走 ​ 1)函数体内会自动创建出一个新的对象 ​ 2)this会指向这个新的对象 ​ 3)函数体内的语句会执行 ​ 4)函数会自动返回这个对像,即使函数没有return语句

  2. js中原型链机制 当查找对象中的某个属性时,如果在当前对象中未找到该属性,则js会自动沿该对象的原型链继续寻找属性

  3. 非箭头函数时,函数中的this指向调用者

结语

此文章已收录至《JavaScript每日一题》专栏,如果你对本专栏有任何建议,欢迎反馈。如果你对此文章中的题目还有不懂的地方,那么请在评论区留言与大家一起讨论吧。
创作不易,少年,就请留个赞再走吧!