js 创建一条通用链表

什么是「链表科普」?

链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。

什么是「顺序存储结构科普」?

在计算机中用一组地址连续的存储单元依次存储线性表的各个数据元素,称作线性表的顺序存储结构。

多数高级语言的「数组」使用「顺序存储结构」,不过早期的 javascript 引擎用了「链式存储结构」。Chrome 的 V8 的数组使用了「顺序存储结构」与「链式存储结构」混合模式;大多数情况下,V8 下的数组是「顺序存储结构」,所以我们就假装 V8 的数组使用的是「顺序存储结构」吧!(-_-! 心虚)

javascript 开发需要「链表」吗?自问自答

大多数情况下 javascript 开发关心的是「数据的逻辑结构」而非「数据的存储结构」,似乎「链表」跟 javascript 开发没什么关系。But…「链表」在一些情况下能有效提升代码的性能,特别是在H5游戏的过程中。

假设有一个业务需要高频率地向一张「线性表科普」插入或删除节点。通常笔者会用数组表示「线性表」,因为 javascript 的数组有一系列成熟好用的 APIs (如:unshift / push / shift / pop / splice 等)可以完成插入与删除节点的操作。但是数组(顺序存储结构)的unshift&shift&splice的算法时间复杂度是 O(n) ,这情况可能「链表」是更好的选择。

图解链表

先看一下最简单的单向链表:

往链表里插入一个节点:

剔除链表里的节点:

往链表里插入一条链表:

剪除链表的一段切片:

通过上面的图示,可以很清晰地了解到单链表的优势:插入节点或链表片段的算法时间复杂度为O(2);删除节点或链表片段的算法时间复杂度为O(1)

实现双向链表

「单向链表」效率虽然高,不过局限性比较大。所以笔者想实现的是「双向链表」。双向链表插入节点或链表的算法时间复杂度为 O(4),删除节点或链表片段的算法时间复杂度为O(2)

双向链表的结构如下:

节点指针 ——「前驱」与「后继」

链表指针 —— 「头指针」、「尾指针」和「游标指针」

用一个匿名对象作为链表上的节点,如下伪代码:

JavaScript


functiongenerateNode(data){

return{

data:data,// 数据域

next:null,// 前驱指针

prev:null// 后继指针

}

}

声明变量HEAD,TAIL,POINTER&length分别指代「头指针」,「尾指针」,「游标指针」和 「链表长度」,那么构建一个双向链表如下伪代码:

JavaScript


letHEAD,TAIL,POINTER,length=0;

// 创建一条长度为5的双向链表

[0,1,2,3,4].forEach((data,index,arr)=>{

letnode=generateNode(data);

// 第一个节点

if(index===0){

HEAD=node;

}

else{

// 指定前驱后继指针

[node.prev,POINTER.next]=[POINTER,node];

// 最后一个节点

index===arr.length-1&&(TAIL=node)

}

// 指向当前节点

POINTER=node;

++length;

});

// 游标指针回退到头部

POINTER=HEAD;

链表结构本身是个很简单的结构,20行左右代码可以完成双向链表数据结构的构建。

定制 APIs

上一节虽然实现了「双向链表」的数据结构,但链表还处在很原始的状态,操作起来比较麻烦,为了方便操作链表得为链表量身定做一套 APIs。数组有一系列成熟且好用的 APIs,笔者想借鉴数组的 APIs 为链表定制以下的 APIs:

NameDetailNameDetailNameDetailNameDetail

shift参见数组unshift参见数组pop参见数组push参见数组

slice参见数组splice参见数组concat参见数组reverse参见数组

sort参见数组indexOf参见数组length[属性]参见数组––

at指针定位prev指针前移next指针后退curr当前指针

first头节点last尾节点remove删除节点clone克隆链表

insertAfter插入节点insertBefore插入节点insertChainAfter插入链表insertChainBefore插入链表

HEAD[属性]头指针TAIL[属性]尾指针setHead重置头指针setTail重置尾指针

POINTER[属性]游标指针(当前位置)setPointer设置当前指针––––

上表与数组同名的 APIs,表示用法与功能与数组一样。

为了突显「链表性」笔者添加了四个insert*。insert*的作用是向主链表指定位置插入节点或链表。APIs 不小心被笔者写多了,这里就不展开介绍它们的实现过程了。有兴趣的同学可以移步:https://github.com/leeenx/es6-utils/blob/master/modules/Chain_v2.js

循环链表

笔者以往都是用数组来模拟循环链表,如下:

JavaScript

Array.prototype.next=function(){

varcur=this[0];

this.push(this.shift());

returncur;

}

vararr=[1,2,3,4,5];

varcount=0;

while(count++<20){

console.log(arr.next());

}

有了Chain类后,可以直接这样写:

JavaScript


letcircle=newChain([1,2,3,4,5]);

// 链表头咬尾

circle.TAIL.next=circle.HEAD;

for(leti=0;i<20;++i){

console.log(chain.next());

}


+群289683894领取资料,交流学习

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 221,548评论 6 515
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,497评论 3 399
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 167,990评论 0 360
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,618评论 1 296
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,618评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,246评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,819评论 3 421
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,725评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,268评论 1 320
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,356评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,488评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,181评论 5 350
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,862评论 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,331评论 0 24
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,445评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,897评论 3 376
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,500评论 2 359

推荐阅读更多精彩内容