JavaScript——双向链表实现
本文版权归博客园和作者吴双本人共同所有,转载和爬虫请注明原文链接 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 = ;
        var tail = ;
        this.insert = function (position, element) {
            if (position >=  && position <= length) {
                var node = new Node(element);
                var current = head;
                var index = ;
                var previous;
                if (position == ) {
                    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 > - && position < length) {
                var current = head;
                var index = ;
                var previous;
                if (position == ) {
                    head = current.next;                    //给head赋值为 下个节点,不关心其是否为null
                    if (length == ) {                        //如果长度为1  head已经为null,则将tail置为null
                        tail = null;
                    } else {                                    //head已经赋值为下个节点
                        head.prev = null;                       //head的prev置为null
                    }
                } else if (position == length - ) {            //最后一个元素
                    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/
如果我的点滴分享对你能有点滴帮助,欢迎点击下方红色按钮关注,我将持续输出分享。
JavaScript——双向链表实现的更多相关文章
- 学习Redis你必须了解的数据结构——双向链表(JavaScript实现)
		
本文版权归博客园和作者吴双本人共同所有,转载和爬虫请注明原文链接 http://www.cnblogs.com/tdws/ 下午分享了JavaScript实现单向链表,晚上就来补充下双向链表吧.对链表 ...
 - JavaScript数据结构与算法(七) 双向链表的实现
		
TypeScript方式实现源码 // 双向链表和普通链表的区别在于, 在链表中, // 一个节点只有链向下一个节点的链接,而在双向链表中,链接是双向的:一个链向下一个元素, // 另一个链向前一个元 ...
 - 《剑指offer》— JavaScript(26)二叉搜索树与双向链表
		
二叉搜索树与双向链表 题目描述 输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表.要求不能创建任何新的结点,只能调整树中结点指针的指向. 思路 递归思想:把大问题转换为若干小问题: 由于Ja ...
 - JavaScript实现双向链表
		
title: JavaScript实现双向链表 toc: false date: 2018-10-07 10:11:36 append(element): 添加元素到链表尾部 insert(posit ...
 - javascript中的链表结构—双向链表
		
1.概念 上一个文章里我们已经了解到链表结构,链表的特点是长度不固定,不用担心插入新元素的时候新增位置的问题.插入一个元素的时候,只要找到插入点就可以了,不需要整体移动整个结构. 这里我们了解一下双向 ...
 - javascript实现数据结构与算法系列:循环链表与双向链表
		
循环链表(circular linked list) 是另一种形式的链式存储结构.它的特点是表中最后一个结点的指针域指向头结点,整个表形成一个环. 循环链表的操作和线性链表基本一致,仅有细微差别. w ...
 - JavaScript数据结构-8.双向链表
		
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
 - javascript普通链表及双向链表
		
写代码的真是心细啊,每一步操作的先后顺序都在卡准. 我其实只是理解了思想和大概的操作. 真正要用时,可能还是要复制,粘贴...:) function LinkedList(){ var Node = ...
 - 学习javascript数据结构(二)——链表
		
前言 人生总是直向前行走,从不留下什么. 原文地址:学习javascript数据结构(二)--链表 博主博客地址:Damonare的个人博客 正文 链表简介 上一篇博客-学习javascript数据结 ...
 
随机推荐
- 去除百度搜索结果中的广告的 js 代码
			
在百度页面下控制台里执行如下代码, 然后关掉控制台 setInterval(() => { try{ Array.from( document.querySelectorAll('#conten ...
 - 【大数据】Zookeeper学习笔记
			
第1章 Zookeeper入门 1.1 概述 Zookeeper是一个开源的分布式的,为分布式应用提供协调服务的Apache项目. 1.2 特点 1.3 数据结构 1.4 应用场景 提供的服务包括:统 ...
 - BZOJ4066 简单题(KD-Tree)
			
板子题. #include<iostream> #include<cstdio> #include<cmath> #include<cstdlib> # ...
 - BZOJ2326 HNOI2011数学作业(矩阵快速幂)
			
考虑暴力,那么有f(n)=(f(n-1)*10digit+n)%m.注意到每次转移是类似的,考虑矩阵快速幂.首先对于位数不同的数字分开处理,显然这只有log种.然后就得到了f(n)=a·f(n-1)+ ...
 - 洛谷P4338 [ZJOI2018]历史(LCT,树形DP,树链剖分)
			
洛谷题目传送门 ZJOI的考场上最弱外省选手T2 10分成功滚粗...... 首先要想到30分的结论 说实话Day1前几天刚刚刚掉了SDOI2017的树点涂色,考场上也想到了这一点 想到了又有什么用? ...
 - ES6学习(二)基础命令
			
一.Let 和 const 作用域的概念:在es5之前是有两个作用域,一个是全局作用域,另外一个是函数作用域,在es6中就多了这样一个块作用域.在这里let 和 const 就是传说中的块作用域,它 ...
 - bzoj千题计划285:bzoj2555: SubString
			
http://www.lydsy.com/JudgeOnline/problem.php?id=2555 后缀自动机,用LCT维护parent树 一个串的出现次数 = parent 树 上 其所在状态 ...
 - 一个ssm综合小案例-商品订单管理----写在前面
			
学习了这么久,一直都是零零散散的,没有把知识串联起来综合运用一番 比如拦截器,全局异常处理,json 交互,RESTful 等,这些常见技术必须要掌握 接下来呢,我就打算通过这么一个综合案例把这段时间 ...
 - li分两列显示
			
只要控制了li的宽度,利用浮动就能实现<style type="text/css"> .my ul { width: 210px; } .my li { width: ...
 - 20155328 2016-2017-2 《Java程序设计》 第8周学习总结
			
20155328 2016-2017-2 <Java程序设计> 第8周学习总结 教材学习内容总结 NIO与NIO2 认识NIO 相对于IO,NIO可以让你设定缓冲区容量,在缓冲区中对感兴趣 ...