链表及链表的常见操作和用js封装一个链表

news2024/11/24 13:22:29

最近在学数据结构和算法,正好将学习的东西记录下来,我是跟着一个b站博主学习的,是使用js来进行讲解的,待会也会在文章后面附上视频链接地址,大家想学习的可以去看看

本文主要讲解单向链表,双向链表后续也会更新

一、什么是链表

二、链表的的常见操作 

三、链表的封装

1、append方法

// 封装 append 追加方法
LinkedList.prototype.append = function() {
    // 1、创建新的节点
    var newNode = new Node(data)

    // 2、判断添加的是否为第一个节点
    if (this.length == 0) { // 2.1 是第一个节点
        this.head = newNode
    } else { // 2.2 不是第一个节点
        // 找到最后一个节点
        var current = this.head
        while (current.next) { // 判断下一个节点是否为 null ,如果为 null 就跳出循环,如果不为 null ,就继续往后寻找,一直找到最后的节点
            current = current.next
        }

        // 最后节点的next指向新的节点
        current.next = newNode
    }

    this.length += 1
}

2、toString 方法

// 封装 toString 字符串方法
LinkedList.prototype.toString = function() {
    // 1、定义变量指向头结点
    var current = this.head
    var listString = "" // 定义变量存储字符串

    // 2、循环获取每一个节点
    while (current) {
        listString += current.data + " "
        current = current.next // 将头结点指向下一个节点
    }

    // 返回字符串
    return listString
}

3、insert 方法

// 封装 insert 插入方法
LinkedList.prototype.insert = function(position, data) { // position 为插入的位置,data 为插入的值
    // 1、对 position 进行越界判断
    if (position < 0 || position > this.length) return false

    // 2、根据 data 创建 newNode
    var newNode = new Node(data)

    // 3、判断插入的位置是否是第一个
    if (position == 0) {
        newNode.next = this.head // 先将新节点的 next 指向当前头节点,因为当前头节点指向下一个节点
        this.head = newNode // 再将头结点指向新节点
    } else {
        var index = 0 // 定义一个索引值
        var current = this.head // 定义一个当前的值为头节点
        var previous = null // 定义一个比当前节点靠前的一个节点
        while (index++ < position) { // 判断索引值与插入的位置进行比较,如果小于要插入的位置,就依次找到当前值与前一个值
            previous = current
            current = current.next
        }

        newNode.next = current // 将新节点的 next 指向当前的值
        previous.next = newNode // 将前一个值的 next 指向新的节点
    }

    // 4、更新长度 length+1
    this.length += 1

    return true
}

4、get 方法

// 4、封装 get 获取方法
LinkedList.prototype.get = function(position) {
    // 1、越界判断
    if(position < 0 || position >= this.length) return null

    // 2、获取对应的 data 
    var current = this.head // 定义当前值为头节点
    var index = 0  // 定义索引值为0
    while(index++ < position){ // 循环找到需要的 position 对应位置的值
        current = current.next
    }

    return current.next
}

5、indexOf 方法

// 5、封装 indexOf 返回指定数据的下标值方法
LinkedList.prototype.indexOf = function(data) {
    // 1、定义变量
    var current = this.head
    var index = 0

    // 2、开始查找
    while (current) { // 判断current是否为null,如果为null才退出循环
        if (current.data == data) { // 判断当前current的值是否为要查找的值,如果是,直接返回对应下标,如果不是,继续往后找
            return index
        }
        current = current.next
        index += 1
    }

    // 3、找到最后没有找到,返回 -1
    return -1
}

6、update 方法

// 6、封装 update 更新指定位置数据的方法
LinkedList.prototype.update = function(position, newData) {
    // 1、越界判断
    if (position < 0 || position >= this.length) return false

    // 2、查找正确的节点
    var current = this.head
    var index = 0
    while (index++ < position) {
        current = current.next
    }

    // 3、将 position 位置的 node 的 data 修改成 newData
    current.data = newData

    return true
}

7、removeAt 方法

// 7、封装 removeAt 删除指定位置的节点方法
LinkedList.prototype.removeAt = function(position) {
    // 1、越界判断
    if (position < 0 || position >= this.length) return null

    // 2、判断是否删除的是第一个节点
    var current = this.head
    if (position == 0) {
        this.head = this.head.next // 如果删除的是第一个节点,直接将头节点指向下一个节点
    } else {
        var index = 0
        var previous = null
        while (index++ < position) {
            previous = current
            current = current.next
        }

        // 找到要删除的节点,然后将这个节点的前一个节点的 next 指向这个节点的下个节点
        previous.next = current.next
    }

    // 3、length-1
    this.length -= 1

    return current.data // 删除节点一般会返回要删除的这个值
}

8、remove 方法

// 8、封装 remove 删除指定数据的节点的方法
LinkedList.prototype.remove = function(data) {
    // 1、获取 data 在列表中的位置
    var position = this.indexOf(data)

    // 2、根据位置信息,删除节点
    return this.removeAt(position)
}

9、isEmpty方法

// 9、封装 isEmpty 判断链表是否为空方法
LinkedList.prototype.isEmpty = function() {
    return this.length == 0
}

10、size方法

// 10、封装 size 返回链表长度方法
LinkedList.prototype.size = function() {
    return this.length
}

完整代码加测试代码

 // 封装链表类
function LinkedList() {
    // 封装内部的类:节点类
    function Node(data) {
        this.data = data
        this.next = null
    }

    // 封装属性
    this.head = null
    // 封装链表的长度
    this.length = 0

    // 1、封装 append 追加方法
    LinkedList.prototype.append = function(data) {
        // 1、创建新的节点
        var newNode = new Node(data)

        // 2、判断添加的是否为第一个节点
        if (this.length == 0) { // 2.1 是第一个节点
            this.head = newNode
        } else { // 2.2 不是第一个节点
            // 找到最后一个节点
            var current = this.head
            while (current.next) { // 判断下一个节点是否为 null ,如果为 null 就跳出循环,如果不为 null ,就继续往后寻找,一直找到最后的节点
                current = current.next
            }

            // 最后节点的next指向新的节点
            current.next = newNode
        }

        this.length += 1
    }

    // 2、封装 toString 字符串方法
    LinkedList.prototype.toString = function() {
        // 1、定义变量指向头结点
        var current = this.head
        var listString = "" // 定义变量存储字符串

        // 2、循环获取每一个节点
        while (current) {
            listString += current.data + " "
            current = current.next // 将头结点指向下一个节点
        }

        // 返回字符串
        return listString
    }

    // 3、封装 insert 插入方法
    LinkedList.prototype.insert = function(position, data) { // position 为插入的位置,data 为插入的值
        // 1、对 position 进行越界判断
        if (position < 0 || position > this.length) return false

        // 2、根据 data 创建 newNode
        var newNode = new Node(data)

        // 3、判断插入的位置是否是第一个
        if (position == 0) {
            newNode.next = this.head // 先将新节点的 next 指向当前头节点,因为当前头节点指向下一个节点
            this.head = newNode // 再将头结点指向新节点
        } else {
            var index = 0 // 定义一个索引值
            var current = this.head // 定义一个当前的值为头节点
            var previous = null // 定义一个比当前节点靠前的一个节点
            while (index++ < position) { // 判断索引值与插入的位置进行比较,如果小于要插入的位置,就依次找到当前值与前一个值
                previous = current
                current = current.next
            }

            newNode.next = current // 将新节点的 next 指向当前的值
            previous.next = newNode // 将前一个值的 next 指向新的节点
        }

        // 4、更新长度 length+1
        this.length += 1

        return true
    }

    // 4、封装 get 获取方法
    LinkedList.prototype.get = function(position) {
        // 1、越界判断
        if (position < 0 || position >= this.length) return null

        // 2、获取对应的 data 
        var current = this.head // 定义当前值为头节点
        var index = 0 // 定义索引值为0
        while (index++ < position) { // 循环找到需要的 position 对应位置的值
            current = current.next
        }

        return current.data
    }

    // 5、封装 indexOf 返回指定数据的下标值方法
    LinkedList.prototype.indexOf = function(data) {
        // 1、定义变量
        var current = this.head
        var index = 0

        // 2、开始查找
        while (current) { // 判断current是否为null,如果为null才退出循环
            if (current.data == data) { // 判断当前current的值是否为要查找的值,如果是,直接返回对应下标,如果不是,继续往后找
                return index
            }
            current = current.next
            index += 1
        }

        // 3、找到最后没有找到,返回 -1
        return -1
    }

    // 6、封装 update 更新指定位置数据的方法
    LinkedList.prototype.update = function(position, newData) {
        // 1、越界判断
        if (position < 0 || position >= this.length) return false

        // 2、查找正确的节点
        var current = this.head
        var index = 0
        while (index++ < position) {
            current = current.next
        }

        // 3、将 position 位置的 node 的 data 修改成 newData
        current.data = newData

        return true
    }

    // 7、封装 removeAt 删除指定位置的节点方法
    LinkedList.prototype.removeAt = function(position) {
        // 1、越界判断
        if (position < 0 || position >= this.length) return null

        // 2、判断是否删除的是第一个节点
        var current = this.head
        if (position == 0) {
            this.head = this.head.next // 如果删除的是第一个节点,直接将头节点指向下一个节点
        } else {
            var index = 0
            var previous = null
            while (index++ < position) {
                previous = current
                current = current.next
            }

            // 找到要删除的节点,然后将这个节点的前一个节点的 next 指向这个节点的下个节点
            previous.next = current.next
        }

        // 3、length-1
        this.length -= 1

        return current.data // 删除节点一般会返回要删除的这个值
    }

    // 8、封装 remove 删除指定数据的节点的方法
    LinkedList.prototype.remove = function(data) {
        // 1、获取 data 在列表中的位置
        var position = this.indexOf(data)

        // 2、根据位置信息,删除节点
        return this.removeAt(position)
    }

    // 9、封装 isEmpty 判断链表是否为空方法
    LinkedList.prototype.isEmpty = function() {
        return this.length == 0
    }

    // 10、封装 size 返回链表长度方法
    LinkedList.prototype.size = function() {
        return this.length
    }

}

// 测试代码
// 1、创建LinkedList
var list = new LinkedList()

// 2、测试append方法
list.append('abc')
list.append('tng')
console.log(list.toString());

// 3、测试insert方法
list.insert(1, '12')
list.insert(2, '333')
console.log(list.toString());

// 4、测试get方法
console.log(list.get(0));
console.log(list.get(1));
console.log(list.get(2));
console.log(list.get(3));

// 5、测试indexOf方法
console.log(list.indexOf('333'));

// 6、测试update方法
list.update(0, '999')
list.update(1, '888')
console.log(list.toString());

// 7、测试removeAt方法
list.removeAt(0)
console.log(list.removeAt(1));
console.log(list.toString());

// 8、测试remove方法
list.remove('tng')
console.log(list.toString());

// 9、测试isEmpty方法
list.isEmpty()
console.log(list.isEmpty());

// 10、测试size方法
list.size()
console.log(list.size());

下面附上b站视频链接,需要学习的可以去看看(JavaScript算法与数据结构

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/478832.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java后端:html转pdf实战笔记

目录 1、htmltopdf有什么用&#xff1f; 2、什么是wkhtmltopdf 3、wkhtmltopdf 参数介绍 4、示例项目 5、预览效果 1、htmltopdf有什么用&#xff1f; htmltopdf 是一款基于wkhtmltopdf技术的html转pdf文档java类库&#xff0c;支持html转pdf和url转pdf。 2、什么是wkhtmltopdf…

Renesa 瑞萨 A4M2 移植文件系统FAT32

配置SDIO底层驱动&#xff08;SD card&#xff09; 跳到对应GPIO&#xff0c;进行复用 将Operation Mode配置 SD_MMC 4Bit&#xff0c;系统会自动配置 会到stacks 根据上面提示&#xff0c;解决错误。 解决第一个error mmc配置 mmc 以上SD卡底层配置完成 使用串口作为…

linux rs485功能增加

目录 串口驱动层级结构 485配置流程 dts相关 配置注册 初始化 485收发切换 delay_after_send 目前linux 内核中已经支持了485的实现&#xff0c;但由于底层驱动的支持情况&#xff0c;导致我们采用不同芯片时需要对底层驱动进行修改&#xff0c;以满足内核485的各个回调…

Linux-基本指令2

文章目录 touch&#xff08;新建一个文件&#xff09;whoami(查看当前用户名)概念&#xff1a;1.你是如何看待指令的&#xff1f;2.我们在执行指令之前&#xff0c;我们应该先做什么? 概念&#xff1a;/tree . (树状显示文件夹和文件)rmdir && rmrmdirrm ctrl c通配符…

【MFAC】基于全格式动态线性化的无模型自适应控制(Matlab代码)

例题来源&#xff1a;侯忠生教授的《无模型自适应控制&#xff1a;理论与应用》&#xff08;2013年科学出版社&#xff09;。 &#x1f449;对应书本 4.4 单输入单输出系统(SISO)全格式动态线性化(FFDL)的无模型自适应控制(MFAC) 上两篇博客分别介绍了基于紧格式和偏格式动态线…

软件分享--安卓纯文本记事本软件,支持多记事本与密码

文章目录 软件名字&#xff1a;LS记事本支持多记事本安全性&#xff1a;备份和恢复&#xff1a;搜索功能&#xff1a;显示功能&#xff1a;字体调节&#xff1a;轻量绿色下载地址 软件名字&#xff1a;LS记事本 支持多记事本 安全性&#xff1a; 1.每个记事本支持设置访问密码…

【Elasticsearch】几点核心概念

文章目录 核心概念系统架构分布式集群单节点集群故障转移水平扩容应对故障 路由计算(确定哪个主分片)分片控制&#xff08;确定哪个节点&#xff09;创建个集群如何查看数据呢&#xff1f;写流程读流程更新流程 分片原理倒序索引文档搜索动态更新索引持久化变更 文档分析内置分…

“Lunar Lobster “现已经可以下载

Canonical近日发布了Ubuntu 23.04&#xff08;Lunar Lobster&#xff09;操作系统&#xff0c;这是对其流行的GNU/Linux发行版的一次重大更新&#xff0c;带来了一些最新和最伟大的技术和开源软件。 被称为 “Lunar Lobster”&#xff0c;Ubuntu 23.04由最新的Linux 6.2内核系列…

【计算机网络】学习笔记:第五章 传输层【王道考研】

基于本人观看学习b站王道计算机网络课程所做的笔记&#xff0c;不做任何获利 仅进行交流分享 特此鸣谢王道考研 若有侵权请联系&#xff0c;立删 如果本篇笔记帮助到了你&#xff0c;还请点赞 关注 支持一下 ♡>&#x16966;<)!! 主页专栏有更多&#xff0c;如有疑问欢迎…

【数据结构与算法】哈希—— 位图 | 布隆过滤器 | 哈希切割

&#x1f431;作者&#xff1a;一只大喵咪1201 &#x1f431;专栏&#xff1a;《数据结构与算法》 &#x1f525;格言&#xff1a;你只管努力&#xff0c;剩下的交给时间&#xff01; 哈希是一种映射思想&#xff0c;这里再讲解两种应用哈希思想的数据结构。 哈希—— 位图 | …

边学边记——数据结构☞堆(包括优先级队列的介绍)

目录 一、堆&#xff08;二叉堆&#xff09; 堆是用来干什么的&#xff1f; 堆是用什么存储结构存储的&#xff1f; 1. 堆的概念 2. 堆的性质 3. 堆的存储方式 下标之间的规则&#xff1a; 4. 堆的基本操作 (1). 向下调整/堆化操作 (2).堆的创建 (3).堆的插入 (4…

2023-04-30:用go语言重写ffmpeg的resampling_audio.c示例,它实现了音频重采样的功能。

2023-04-30&#xff1a;用go语言重写ffmpeg的resampling_audio.c示例&#xff0c;它实现了音频重采样的功能。 答案2023-04-30&#xff1a; resampling_audio.c 是 FFmpeg 中的一个源文件&#xff0c;其主要功能是实现音频重采样。 音频重采样是指将一段音频数据从一个采样率…

duubo+zookeeper

1、Dubbo简介 1. Dubbo是什么&#xff1f; 高性能、轻量级、开源、基于java Dubbo 是阿里集团开源的远程服务调用的分布式框架&#xff08;告别Web Service模式中的WSDL&#xff0c;以服务者与消费者的方式在dubbo上注册&#xff09; 协议和序列化框架都可以插拔是及其鲜明…

【办公类-22-04】周计划系列(4)-生成“周计划”(提取旧docx指定段落的内容,写入EXCLE模板,再次生成新docx)

代码相当复杂&#xff0c;操作很繁琐&#xff0c;自己都要研究半天T_T 文件夹展示 01提取提取新表的已有内容&#xff08;提取大8班、大7班的新版本里面的额内容&#xff09; &#xff08;需要里面的一些反思&#xff0c;用来占位&#xff09; 这里有一份根据新模板用Python批…

spring2:创建和使用

目录 1.创建Spring项目 1.1创建Maven类 1.2添加Spring支持框架 1.3添加启动类 2.存储Bean对象 2.0 spring项目中添加配置文件(第一次) 2.1创建Bean 2.2把Bean注册到容器中 3.获取并使用Bean对象 3.1创建上下文 3.2获取指定Bean对象 getBean()方法 --> 获取什么…

双周赛103(模拟、网格图BFS、树状数组)

文章目录 双周赛103[6406. K 个元素的最大和](https://leetcode.cn/problems/maximum-sum-with-exactly-k-elements/)模拟 [6405. 找到两个数组的前缀公共数组](https://leetcode.cn/problems/find-the-prefix-common-array-of-two-arrays/)模拟 [6403. 网格图中鱼的最大数目](…

Java 基础进阶篇(一)——— static 静态关键字与单例模式

文章目录 一、static 静态关键字1.1 静态成员变量与实例成员变量1.2 静态成员方法与实例成员方法1.3 static 访问注意事项1.4 内存使用情况 二、工具类三、代码块四、单例模式4.1 饿汉单例4.2 懒汉单例 一、static 静态关键字 static&#xff1a;代表静态的意思&#xff0c;可…

【博学谷学习记录】超强总结,用心分享丨人工智能 AI项目 collate_fn函数理解与记录

目录 Dataloader取数据过程使用报错&#xff1a;默认collate_fn处理不同长度的数据自定义collate_fn伪代码示例 Dataloader取数据过程 取出大小等同于batch size的index列表;将列表列表中的index输入到dataset的getitem()函数中&#xff0c;取出该index对应的数据;对每个index…

一种基于坑位模版的分页方案

一. 概述 1.1 业务诉求 想象一个向用户展示数据的下拉列表&#xff0c;数据的来源有多种方式。支持在每一页都按固定的数据源类型及顺序展示。 1.2 业务场景 up主的主页展示带货商品列表 商品来源有多种&#xff1a;up主自选、官方推荐的、根据up主风格AI推荐用户推荐视频列表…

【编辑刷新数据-汽车品牌展示 Objective-C语言】

一、我们这个利用可重用cell展示汽车品牌案例,就说完了,然后我们再给大家说一个什么东西,就是这个刷新数据这个东西, 1.刷新数据这个东西,我们用的就是代理,再把代理相当于是再给大家复习一下,再把代理复习一下,顺便再说一下怎么刷新数据, 2.接下来,要实现一个什么功…