用JavaScript撸一个静态链表
最近重新开始翻起《大话数据结构》,看到了静态链表部分里面讲C语言是利用数组模拟,觉得十分有趣。但是在JavaScript中,也可以用类似的方式去实现,定义一个数据域和一个结点域,然后实现链表的基础操作。弱类型语言没有指针,所以需要自己区实现。算法的乐趣就在于解决一些思路上的问题,直击问题的本质。
首先可以定义Node类,如下所示:
class Node {
constructor(value) {
this.data = value;
this.next = null;
}
}
然后实现StaticLinkedList类,先定义简单的append和display方法:
class StaticLinkedList {
constructor() {
this.head = null;
this.length = 0;
}
append(value) {
const newNode = new Node(value);
this.length++;
if (this.head === null) {
this.head = newNode;
return;
}
let current = this.head;
while (current.next != null) {
current = current.next;
}
current.next = newNode;
}
display() {
console.log('the static linked list is:\r\n');
let current = this.head;
if (current === null) {
console.log('empty!');
return;
}
while (current !== null) {
console.log(JSON.stringify(current));
console.log(`its value is ${current.data}\r\n`);
current = current.next;
}
}
}
其中append方法是在链表尾部添加新的Node对象,display方法可以打印出Node对象和它的数据。使用这个静态链表类也很简单,比如添加4个结点到这个链表里面:
const staticLinkedList = new StaticLinkedList();
staticLinkedList.append(3);
staticLinkedList.append(7);
staticLinkedList.append(16);
staticLinkedList.append(24);
我们还应该提供更加灵活添加结点的方法,比如我想在第三个结点位置插入一个新的结点,数值为11,那么现有的append方法就不适用了,需要定义一个新的插入结点的方法,代码如下:
/**
* Method to insert an new element at the specific location
*
* @param {*} elementValue the value of the element that to be inserted
* @param {*} index the position of the element, from 1 to maximum of the list
* @returns true/false
*/
insertAt(elementValue, index) {
if (index < 1 || index > this.length + 1) {
console.log('index is out of the range!');
return false;
}
const newNode = new Node(elementValue);
let startPos = 1;
let current = this.head;
while (startPos < index - 1) {
current = current.next;
startPos++;
}
newNode.next = current.next;
current.next = newNode;
this.length++;
return true;
}
这段代码需要理解的是新结点如何添加到链表的那两行代码,首先是newNode.next = current.next,这行代码是把新结点的next指向了原来插入前位置的结点的下一个结点。然后current.next = nextNode,把新结点替换掉原来该位置的结点。
为了更好地理解,我画了一张示意图:

要注意的是step1和step2的顺序不能颠倒,否则会导致代码运行错误。
然后我们还需要定义一个移除指定位置结点的方法,如下所示:
removeAt(index) {
if (index < 1 || index > this.length + 1) {
console.log('index is out of the range!');
return;
}
let current = this.head;
let startPos = 1;
let previous = null;
while (startPos < index) {
previous = current;
current = current.next;
startPos++;
}
previous.next = current.next;
this.length--;
}
我对previous.next = current.next也画了一张示意图,删除原来结点,需要把它前面一个结点的next指向该结点的next。

总结:
静态链表的添加和移除略有不同,需要利用Node中的next进行模拟指针操作,让新的结点加入到链表,让需要被删除的结点直接从上一个结点的next指向到原有结点的next。
用JavaScript撸一个静态链表的更多相关文章
- 【数据结构】单链表&&静态链表详解和代码实例
喜欢的话可以扫码关注我们的公众号哦,更多精彩尽在微信公众号[程序猿声] 01 单链表(Singly Linked List ) 1.1 什么是单链表? 单链表是一种链式存储的结构.它动态的为节点分配存 ...
- javascript数据结构与算法--链表
链表与数组的区别? 1. 定义: 数组又叫做顺序表,顺序表是在内存中开辟一段连续的空间来存储数据,数组可以处理一组数据类型相同的数据,但不允许动态定义数组的大小,即在使用数组之前必须确定数组的大小. ...
- 使用C语言描述静态链表和动态链表
静态链表和动态链表是线性表链式存储结构的两种不同的表示方式. 静态链表的初始长度一般是固定的,在做插入和删除操作时不需要移动元素,仅需修改指针,故仍具有链式存储结构的主要优点. 动态链表是相对于静态链 ...
- 静态链表 C语言描述
静态链表1.下标为0的游标存放最后存放数据节点的游标,即是第一个没有存放元素(备用链表)的下标2.最后一个的节点存放第一个由数值得下标3.第一个和最后一个都不存放数据 即是备用链表的第一个的下标 4. ...
- 03静态链表_StaticLinkList--(线性表)
#include "string.h" #include "ctype.h" #include "stdio.h" #include &qu ...
- 从零开始,在windows上用nodejs搭建一个静态文件服务器
从零开始,在windows上用nodejs搭建一个静态文件服务器 首先安装nodejs: 新建一个node文件夹 下载node.exe到该文件夹 下载npm然后解压到该文件夹 现在node文件夹是这样 ...
- 高仿“点触验证码”做的一个静态Html例子
先上源码: <html> <head> <title>TouClick - Designed By MrChu</title> <meta htt ...
- java与数据结构(2)---java实现静态链表
结点类 1 //结点类 2 class Node<T> { 3 private T data; 4 private int cursor; 5 6 Node(T data, int cur ...
- 静态链表实现 (A-B)U(B-A)
图中黄色部分为(A-B)U(B-A)的实际意义,用结构数组做静态链表来实现该表达式 大致流程是先建立A链表,接着将挨个输入的B中元素在A链表中遍历.如果没找到,就加到A链表结尾下标为endpointe ...
- 静态链表实现(A-B)+(B-A)【代码】
-----------------------------------------------第一次发代码,写在前面------------------------------------------ ...
随机推荐
- 逍遥自在学C语言 | 位运算符&的高级用法
前言 在上一篇文章中,我们介绍了&运算符的基础用法,本篇文章,我们将介绍& 运算符的一些高级用法. 一.人物简介 第一位闪亮登场,有请今后会一直教我们C语言的老师 -- 自在. 第二位 ...
- Java设计模式 —— 建造者模式
8 建造者模式 8.1 建造者模式概述 Builder Pattern:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示. 建造者模式可以将部件本身和它们的组装过程分开,关注如 ...
- 【c#表达式树】最完善的表达式树Expression.Dynamic的玩法
引言 在我第一次写博客的时候,写的第一篇文章,就是关于表达式树的,链接:https://www.cnblogs.com/1996-Chinese-Chen/p/14987967.html,其中,当时一 ...
- day66:Linux:nginx+uwsgi+django跑python项目
目录 0.uwsgi简述 1.使用uwsgi+django运行demo 2.nginx+uwsgi+django跑pythonav项目 0.uwsgi简述 1.什么是wsgi WSGI,全称Web S ...
- 还原win10任务管理器的内存dump功能之——程序逆向分析(待完成)
逆向分析工作基本完成,笔记待完成.
- CesiumJS 源码杂谈 - 从光到 Uniform
目录 1. 有什么光 2. 光如何转换成 Uniform 以及何时被调用 2.1. 统一值状态对象(UniformState) 2.2. 上下文(Context)执行 DrawCommand 2.3. ...
- Kubernetes集群调度增强之超容量扩容
作者:京东科技 徐宪章 1 什么是超容量扩容 超容量扩容功能,是指预先调度一定数量的工作节点,当业务高峰期或者集群整体负载较高时,可以使应用不必等待集群工作节点扩容,从而迅速完成应用横向扩容.通常情况 ...
- springboot整合cas回调地址使用nginx配置出错
nginx配置后台为 location /apis springboot基础cas回调时访问地址为nginx域名+apis回调.为什么没有成功.页面只回调域名+登录方法路径,而不是域名+apis+登录 ...
- 高阶函数_函数柯里化 以及 setState中动态key
使用柯里化: 1 state = { 2 username: "", 3 password: "", 4 }; 5 render() { 6 return ( ...
- 关于OA系统的取数依据,以及如何逆向查询数据错误的思路。
1.正文 00.起因 源于财务在群里发的问题.我估计对于很多同事,又会像往常一样充满疑问,尤其是对于oa的取数会有疑问,然后业务能力极差的那部分,又会想到这是运营的问题(话说关运营什么事?),这是项目 ...