不会c和cpp也能学数据结构——javascript实现双向链表

蜗牛      2022-02-07     250

关键词:

本文版权归博客园和作者吴双本人共同所有,转载和爬虫请注明原文链接  http://www.cnblogs.com/tdws/

下午分享了JavaScript实现单向链表,晚上就来补充下双向链表吧。对链表的实现不是很了解的可以移步:http://www.cnblogs.com/tdws/p/6033209.html

双向链表与链表的不同之处主要在于他的双向查找。因为在这种结构中我们设计了每个节点的prev(向上查找)的引用或指针和next(向下查找)的引用或指针。得益于这种结构你能做到正向和反向的查找。你也可以在查找某个index位置的元素时,根据其长度计算,到底是使用正向还是反向,这取决于你自己。

直接上代码吧,详解在注释里:

先看一下代码的整体结构:

下面是具体实现:

    function DoublyLinkedList() {
        var Node = function (element) {
            this.element = element;
            this.next = null;               //下一个是谁
            this.prev = null;               //上一个是谁
        };
        var head = null;
        var length = 0;
        var tail = 0;
        this.insert = function (position, element) {
            if (position >= 0 && position <= length) {
                var node = new Node(element);
                var current = head;
                var index = 0;
                var previous;
                if (position == 0) {                            
                    if (head == null) {                             //空链表
                        head = node;
                        tail = node;
                    } else {
                        head = node;                                  //新元素作为头部
                        head.next = current;                          //头部的下一个节点是旧头部
                        current.prev = node;                           //旧头部的上一个节点是新元素
                    }
                } else if (position == length) {                        //尾部
                    current = tail;
                    current.next = node;                                 //旧尾部的下一个节点 是新节点
                    node.prev = current;                                 //新节点的上一个节点是旧尾部
                    tail = node;                                         //更新尾部节点为新元素
                } else {
                    while (index < position) {
                        previous = current;
                        current = current.next;
                        index++;
                    }                                                   //遍历后current为当前position的节点
                    node.next = current;                                //新节点的next是current             
                    previous.next = node;                                //上节点的下一个是新元素

                    node.prev = previous;                               //新元素的上个节点是previous
                    current.previous = node;                            //current的上个节点是新元素
                }
                length++;
                return true;
            } else {
                return false;
            }
        };

        this.removeAt = function (position) {
            if (position > -1 && position < length) {
                var current = head;
                var index = 0;
                var previous;
                if (position == 0) {
                    head = current.next;                    //给head赋值为 下个节点,不关心其是否为null
                    if (length == 1) {                        //如果长度为1  head已经为null,则将tail置为null
                        tail = null;
                    } else {                                    //head已经赋值为下个节点
                        head.prev = null;                       //head的prev置为null
                    }
                } else if (position == length - 1) {            //最后一个元素
                    current = tail;
                    tail = current.prev;
                    tail.next = null;
                } else {
                    while (index++ < position) {                    //普通中间元素
                        previous = current.prev;                    
                        current = current.next;
                    }                                               //遍历后得到当前position元素
                    previous.next = current.next;                    //当前osition元素的prev指向当前postion元素的下个元素
                    current.next.prev = previous;                       //总之越过一个
                }
                length--;
                return current.element;
            } else {
                return null;
            }
        };

        this.getLength = function () {
            return length;
        };

        this.toString = function () {
            var current = head;
            var string = '';
            while (current) {
                string += ',' + current.element;
                current = current.next;
            }
            return string;
        };
    }

废话也不多说了,关于双向链表的文章网上一搜一大堆。

顺便提到的就是Redis五大数据类型中的List列表类型,我们知道Redis列表我们可以正向查找元素,也可以反向查找元素。这也算是双向链表在实际中的一大用途吧。

Redis相关文章链接 http://www.cnblogs.com/tdws/tag/NoSql/

 

如果我的点滴分享对你能有点滴帮助,欢迎点击下方红色按钮关注,我将持续输出分享。

 

菜鸟也能学cocos2dx3.0浅析刀塔传奇(下)(代码片段)

首先我们讲点话外的东西,异步载入:众所周知。loading里面一般都是载入数据的,那么是怎么载入的呢?Director::getInstance()->getTextureCache()->addImageAsync(conststd::string&path,conststd::function<void(Texture2D*)>&callback)//參 查看详情

前端也能学算法:由浅入深讲解动态规划(代码片段)

动态规划是一种常用的算法思想,很多朋友觉得不好理解,其实不然,如果掌握了他的核心思想,并且多多练习还是可以掌握的。下面我们由浅入深的来讲讲动态规划。斐波拉契数列首先我们来看看斐波拉契数列,这是一个大家... 查看详情

前端也能学算法:由浅入深讲解贪心算法(代码片段)

贪心算法是一种很常见的算法思想,而且很好理解,因为它符合人们一般的思维习惯。下面我们由浅入深的来讲讲贪心算法。找零问题我们先来看一个比较简单的问题:假设你是一个商店老板,你需要给顾客找零n元钱,你手上... 查看详情

零基础学python有什么建议?零基础也能学python(附学习资料)

首先零基础是能学python的,很多编程大神入门之前都选择先学习Python,所以想学就大胆去学吧,没学之前谁不是零基础,就算是现在才下定决心学也不怕,学习Python什么时候都不算晚。零基础如何学好pythonÿ... 查看详情

vscode写c代码,结构成员不会自动提示,要怎么设置吗?

定义了DPF_Parameter结构体,在写代码的时候,自动补全的内容不是结构体的成员。安装好官方的C/C++插件还不够,需要解决头文件路径的问题,如果头文件在workspace文件夹下,鼠标点一下波浪线提示错误的头文件会有小灯泡,点小... 查看详情

cpp数据和c

...量可以在程序执行过程中变化和指定,而常量不可以。【数据类型关键字】int  long  short  unsigned  char   float  double  _Bool  _Complex(复数)  _Imaginary(虚数) 【int类型】整数类型之所以有这么多种(int,uns... 查看详情

学编程学不下去?给你几个好东西,玩游戏也能学编程

...戏的方式,加强你的编程学习!是的,玩游戏也能学编程,摆脱枯燥的学习方式。​一、CodinGame|游戏化编程教学平台CodinGame虽然和游戏有关但是并不是游戏开发,只是简单的游戏模式,每一个练习背后的... 查看详情

c_cpp带有类定义和结构定义的头文件。(代码片段)

查看详情

跟尹成前辈学c/c++003

数据结构与算法程序=数据结构+算法语言是一种工具语言工具(c,c++)--程序设计方法(面向过程、面向对象)——数据结构(二叉树、队列、栈、红黑树、链表……)——算法(快速排序算法、冒泡排序算... 查看详情

javascrip笔记心得(持续更新)(代码片段)

JavaScrip笔记心得一、JavaScript简介1、JavaScript2、JavaScript使用方法3、JavaScript的核心构成4、Javascript的代码注释5、Javascript的数据类型6、变量的声明和赋值7、表达式与运算符二、JavaScrip语句和函数1、if分支结构2、switch分支结构3、whi... 查看详情

javascrip笔记心得(持续更新)(代码片段)

JavaScrip笔记心得一、JavaScript简介1、JavaScript2、JavaScript使用方法3、JavaScript的核心构成4、Javascript的代码注释5、Javascript的数据类型6、变量的声明和赋值7、表达式与运算符二、JavaScrip语句和函数1、if分支结构2、switch分支结构3、whi... 查看详情

python太火了,快毕业了我想当程序员,但是我不是学计算机的,能学的好python吗?

...以报名Python全栈工程师。参考技术A不是研究烹饪的,就不会做饭了?Python只是工具,学习即可。 参考技术B多多对比吧,看看口碑之类的,有试听的话先去试听下,这样也能避免掉坑 查看详情

c语言中的.c和.cpp有啥区别?

...d指针可以给任意类型指针赋值。2、.cpp:必须先进行强制数据类型转换再赋值。参考资料来源:百度百科-cpp参考资料来源:百度百科-c 查看详情

.cpp 和 .c 文件的替换参考 [关闭]

...题得到解决。我遇到了问题。我的makefile是基于thisanswer的结构:LIB=mylib.soCPPSRCS+=hel 查看详情

c_cpp查找=重复xor具有相同的数字不会更改输出字符。(代码片段)

查看详情

添加 .h 和 .cpp 文件后 Eclipse 不会构建项目

】添加.h和.cpp文件后Eclipse不会构建项目【英文标题】:Eclipsewon\'tbuildprojectafteradding.hand.cppfiles【发布时间】:2015-05-0600:12:54【问题描述】:我创建了一个简单的C++项目并自己制作了makefile。makefile如下所示:all:project1.execlean:rmmain.... 查看详情

使用 Automake 编译 *.cpp 和 *.c

...*.cwithAutomake【发布时间】:2020-06-1610:13:28【问题描述】:结构:-myProject-Makefile.am-configure.ac-src-Makefile.am-main.c-test.c-test.h当我尝试编译时,我收到错误未定义的对test.c中函数的引用。Makefile.am:AUTOMAKE_OP 查看详情

不会es6能学vue吗

16参考技术A学vue最好是要会es6。ES6是基础,一定要学。TypeScript是一种主流,也要学。知识不要怕多怕学,入了这行,就要有持续学习的心理准备。况且用框架编程,不管是ES6还是啥TypeScript,都不大需要每个知识点都用到,基本... 查看详情