最近重新开始翻起《大话数据结构》,看到了静态链表部分里面讲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撸一个静态链表的更多相关文章

  1. 【数据结构】单链表&&静态链表详解和代码实例

    喜欢的话可以扫码关注我们的公众号哦,更多精彩尽在微信公众号[程序猿声] 01 单链表(Singly Linked List ) 1.1 什么是单链表? 单链表是一种链式存储的结构.它动态的为节点分配存 ...

  2. javascript数据结构与算法--链表

    链表与数组的区别?  1. 定义: 数组又叫做顺序表,顺序表是在内存中开辟一段连续的空间来存储数据,数组可以处理一组数据类型相同的数据,但不允许动态定义数组的大小,即在使用数组之前必须确定数组的大小. ...

  3. 使用C语言描述静态链表和动态链表

    静态链表和动态链表是线性表链式存储结构的两种不同的表示方式. 静态链表的初始长度一般是固定的,在做插入和删除操作时不需要移动元素,仅需修改指针,故仍具有链式存储结构的主要优点. 动态链表是相对于静态链 ...

  4. 静态链表 C语言描述

    静态链表1.下标为0的游标存放最后存放数据节点的游标,即是第一个没有存放元素(备用链表)的下标2.最后一个的节点存放第一个由数值得下标3.第一个和最后一个都不存放数据 即是备用链表的第一个的下标 4. ...

  5. 03静态链表_StaticLinkList--(线性表)

    #include "string.h" #include "ctype.h" #include "stdio.h" #include &qu ...

  6. 从零开始,在windows上用nodejs搭建一个静态文件服务器

    从零开始,在windows上用nodejs搭建一个静态文件服务器 首先安装nodejs: 新建一个node文件夹 下载node.exe到该文件夹 下载npm然后解压到该文件夹 现在node文件夹是这样 ...

  7. 高仿“点触验证码”做的一个静态Html例子

    先上源码: <html> <head> <title>TouClick - Designed By MrChu</title> <meta htt ...

  8. java与数据结构(2)---java实现静态链表

    结点类 1 //结点类 2 class Node<T> { 3 private T data; 4 private int cursor; 5 6 Node(T data, int cur ...

  9. 静态链表实现 (A-B)U(B-A)

    图中黄色部分为(A-B)U(B-A)的实际意义,用结构数组做静态链表来实现该表达式 大致流程是先建立A链表,接着将挨个输入的B中元素在A链表中遍历.如果没找到,就加到A链表结尾下标为endpointe ...

  10. 静态链表实现(A-B)+(B-A)【代码】

    -----------------------------------------------第一次发代码,写在前面------------------------------------------ ...

随机推荐

  1. 二进制安装Kubernetes(k8s) v1.24.3 IPv4/IPv6双栈

    二进制安装Kubernetes(k8s) v1.24.3 IPv4/IPv6双栈 Kubernetes 开源不易,帮忙点个star,谢谢了 介绍 kubernetes(k8s)二进制高可用安装部署,支 ...

  2. python内在模块之winreg --- Windows 注册表访问

    winreg --- Windows 注册表访问¶ 这些函数将 Windows 注册表 API 暴露给 Python.为了确保即便程序员忽略了显式关闭句柄,该句柄依然能够正确关闭,它使用了一个 han ...

  3. [网络/Linux]CentOS7:OpenSSH升级到7.9p1 | 含: 安装Telnet/OpenSSH【telnet/ssh】

    [Q0 OpenSSH/sshd/ssh/scp/sftp,及OpenSSL这些软件组件之间有什么联系吗?] 请跳转咱的另一篇博文,相信阅读完后,你会清楚很多: [网络/SSH]OpenSSH: ss ...

  4. shell读取配置文件-sed命令

    在编写启动脚本时,涉及到读取配置文件,特地记录下shell脚本读取启动文件的方式.主要提供两种格式的读取方式,方式一配置文件采用"[]"进行分区,方式二配置文件中需要有唯一的配置项 ...

  5. 【LeetCode动态规划#08】完全背包问题实战与分析(零钱兑换II)

    零钱兑换II 力扣题目链接(opens new window) 给定不同面额的硬币和一个总金额.写出函数来计算可以凑成总金额的硬币组合数.假设每一种面额的硬币有无限个. 示例 1: 输入: amoun ...

  6. C# 从0到实战 命名空间

    什么是命名空间 命名空间是C#为了解决类名冲突而产生的一种方案,通过特定的前缀来标识一个类,使得编程者可以在自己的命名空间中自由使用各种类名,这很类似于Java中的包. 一般新手学习C#都会使用一个 ...

  7. Java 新的生态型应用开发框架,Solon v2.2.13 发布

    Java 新的生态型应用开发框架,Solon :更快.更小.更简单.从零开始构建,有自己的标准规范与开放生态: 150多个生态插件,可以满足各种场景开发 大量的国产框架适配,可以为应用软件国产化提供更 ...

  8. 真实场景sql优化持续更新(老司机必备)

    概述 下述场景,均来自实际产品线上经验,出于保密考量,所有需求场景都是仿造的,模拟遇到过的真实场景. 场景一: 统计数据(Order by 不具备唯一性导致的分页数据混乱) 需求 在实际业务场景中,我 ...

  9. Locust 运行方式

      命令参数方式运行 # -*- coding: utf-8 -*- from locust import TaskSet, task, User ''' 命令行参数运行示例代码 ''' class ...

  10. 魔王语言问题c语言实现及思路求解

    文章目录 问题描述及需求分析 需求分析 问题分析及实现路线(队列+栈) 结构体核心代码 队列核心代码 入队 出队 栈的核心代码 入栈 出栈 全部代码 单向循环队列和栈(改变B的对应密码) 总结 问题描 ...