[js] 请使用 js 实现一个双向链表

链表结构是我们在面试中经常会被问起的较为基础的数据结构问题,起初学习数据结构使用的是C++语言,最近在做前端面试题的过程中没碰到了需要用js实现双链表的需求,百度出来的文章发现可很多错误,于是索性自己重新写了,并且列出了一些错误点,这里给大家较为详细的一步步看一下实现思想和步骤,相较于C++语言,js的实现可以说是很简单了,不需要创建繁琐的对象,更加直观易懂;
首先我们来看一下双向链表的结构图:
在这里插入图片描述
每个结点包含三部分,指向前一个结点的指针(pre),指向后一个节点的指针(next),以及自己的数据部分(element),于是我们就可以先写出结点对象

function Node:定义结点对象

function Node(element) {this.element = elementthis.next = nullthis.previous = null
}

然后我们开始实现插入链表的算法
在这里插入图片描述

(声明)下面函数中的this是我们最后初始化链表的实例,这里大家不要疑惑。可以拉到最下面我们初始化链表那里,相信你会明白呦

**`function insert`:插入节点**function insert(newelement, currentelement) {var newNode = new Node(newelement)var currentNode = this.find(currentelement)if (currentNode === 'error') {console.log('无法插入,要插入节点不存在')return}if (currentNode.next != null) {newNode.next = currentNode.nextcurrentNode.next = newNodenewNode.previous = currentNodenewNode.next.previous = newNode} else {currentNode.next = newNodenewNode.previous = currentNode}
}

function find:找到插入位置

function find(element) {var currentNode = this.headwhile (currentNode.element != element) {/*如果找到最后一个节点还没有找到我们的插入点,那么我们就会返回错误*/if (currentNode.next == null) {console.log('can not find this node; maybe not have this node')return 'error'}currentNode = currentNode.next}return currentNode
}

接下来是移除结点的实现,如果看懂了插入节点的实现,那么移除就会很简单了,相信大家都可以很快明白,这里就直接贴出实现代码;

function remove:移除一个结点function remove(element) {var currentNode = this.find(element)if (currentNode === 'error') {console.log('要移除节点不存在')return}/*首先是不是头尾节点的情况*/if (currentNode.next != null && currentNode.previous != null) {currentNode.previous.next = currentNode.nextcurrentNode.next.previous = currentNode.previouscurrentNode.next = nullcurrentNode.previous = null} else if (currentNode.previous == null) {/*当是头节点的时候*/this.head = currentNode.nextcurrentNode.next.previous = nullcurrentNode.next = null} else if (currentNode.next == null) {/*当是尾节点的时候 */currentNode.previous.next = nullcurrentNode.previous = null}
}

截止到这里我们基本功能已经有了,下面使我们根据自己需要可以自定义一些其他函数

function lastNode:找到最后一个节点function lastNode() {var head = this.headwhile (head.next != null) {head = head.next}return head     //这里head在尾节点的位置
}
function append:将要添加的结点放在链表末尾function append(element) {var lastnode = this.lastNode()var newNode = new Node(element)lastnode.next = newNodenewNode.previous = lastnode
}
function showlist:将链表所有的结点打印出来function showlist() {var head = this.headdo {console.log(head.element)head = head.next} while (head != null)// 大家可以看一下下面注释内容存在什么问题,留给大家思考一下// while (head.next != null) {//   console.log(head.element)//   head = head.next// }
}

接下来是对链表进行初始化,这也是上述函数中所有this所代表的实例

function initlist:初始化链表,并将所有方法注册到链表中

function initlist() {this.head = new Node('one')this.find = findthis.insert = insertthis.remove = removethis.showlist = showlistthis.lastNode = lastNodethis.append = append
}var list = new initlist()
list.insert('two', 'one')
list.insert('four', 'two')
list.insert('three', 'two')// console.log(list.head.next)
list.showlist()
list.append('A')
list.append('B')
list.insert('B2', 'B')
list.showlist()
console.log(list.lastNode())
// list.remove('one')
// list.showlist()
console.log(list.find('A').previous)
// console.log(list.find('four').previous)
// console.log(list.head.element)

下面是运行结果:
在这里插入图片描述
源码:

function Node(element) {this.element = elementthis.next = nullthis.previous = null
}
function find(element) {var currentNode = this.headwhile (currentNode.element != element) {if (currentNode.next == null) {console.log('can not find this node; maybe not have this node')return 'error'}currentNode = currentNode.next}return currentNode
}
function insert(newelement, currentelement) {var newNode = new Node(newelement)var currentNode = this.find(currentelement)if (currentNode === 'error') {console.log('无法插入,要插入节点不存在')return}if (currentNode.next != null) {newNode.next = currentNode.nextcurrentNode.next = newNodenewNode.previous = currentNodenewNode.next.previous = newNode} else {currentNode.next = newNodenewNode.previous = currentNode}
}
function remove(element) {var currentNode = this.find(element)if (currentNode === 'error') {console.log('要移除节点不存在')return}/*首先是不是头尾节点的情况*/if (currentNode.next != null && currentNode.previous != null) {currentNode.previous.next = currentNode.nextcurrentNode.next.previous = currentNode.previouscurrentNode.next = nullcurrentNode.previous = null} else if (currentNode.previous == null) {/*当是头节点的时候*/this.head = currentNode.nextcurrentNode.next.previous = nullcurrentNode.next = null} else if (currentNode.next == null) {/*当是尾节点的时候 */currentNode.previous.next = nullcurrentNode.previous = null}
}
function showlist() {var head = this.headdo {console.log(head.element)head = head.next} while (head != null)// while (head.next != null) {//   console.log(head.element)//   head = head.next// }
}
function initlist() {this.head = new Node('one')this.find = findthis.insert = insertthis.remove = removethis.showlist = showlistthis.lastNode = lastNodethis.append = append
}
function append(element) {var lastnode = this.lastNode()var newNode = new Node(element)lastnode.next = newNodenewNode.previous = lastnode
}
function lastNode() {var head = this.headwhile (head.next != null) {head = head.next}return head
}
var list = new initlist()
list.insert('two', 'one')
list.insert('four', 'two')
list.insert('three', 'two')// console.log(list.head.next)
list.showlist()
list.append('A')
list.append('B')
list.insert('B2', 'B')
list.showlist()
console.log(list.lastNode())
// list.remove('one')
// list.showlist()
console.log(list.find('A').previous)
// console.log(list.find('four').previous)
// console.log(list.head.element)

个人简介

我是歌谣,欢迎和大家一起交流前后端知识。放弃很容易,
但坚持一定很酷。欢迎大家一起讨论

主目录

与歌谣一起通关前端面试题

[js] 请使用 js 实现一个双向链表相关推荐

  1. [js] 请使用js实现一个秒表计时器的程序

    [js] 请使用js实现一个秒表计时器的程序 <!DOCTYPE html> <html lang="en"><head><meta ch ...

  2. [js] 请使用js实现商品的自由组合,并说说你的思路

    [js] 请使用js实现商品的自由组合,并说说你的思路 <!DOCTYPE html> <html lang="en"><head><me ...

  3. [js] 请写一个性能最好的深度克隆对象的方法

    [js] 请写一个性能最好的深度克隆对象的方法 const deepClone = (obj) => {const copy = obj instance Array ? [] : {};for ...

  4. 使用js在桌面上写一个倒计时器_论一个倒计时器的性能优化之路

    原文发表于 2018.05.25,搬运自个人博客. 引子 回顾这半年,扛需求能力越来越强,业务代码也是越写越多.但稍一认真看看这些当时为了满足快速上线所码的东西,问题其实还是不少.这次就从一个简单的计 ...

  5. 分享一个基于jQuery,backbone.js和underscore.js的消息提示框架 - Backbone.Notifier

    在线演示  本地下载 我们曾今在以前的文章中介绍过jQuery的警告和提示框插件,今天这里我们介绍一个开源的消息提示框架 Backbone.Notifier,目前版本为version0.1.使用这个框 ...

  6. css倒序循环,不借助后台和 JS ,只用 CSS 让一个列表编号倒序

    我正在做一个项目,其中有一个倒序的列表.列表创建时间降序排序的,这里我想在语义和视觉上都能体现出来(让列表显示对应的编号,编号越大表示是最新的).网上做了一些研究,找到了一些有趣的解决办法,有些很好, ...

  7. [译]简单得不得了的教程-一步一步用 NODE.JS, EXPRESS, JADE, MONGODB 搭建一个网站

    原文: http://cwbuecheler.com/web/tutorials/2013/node-express-mongo/ 原文的源代码在此 太多的教程教你些一个Hello, World!了, ...

  8. axios下载图片 node_vue+node.js手把手教你搭建一个直播平台(二)

    上一期,帅气的小羽给老铁们介绍了直播平台的项目的后端搭建,这期就让小羽带大家来搭建一下前端的框架. 1.创建前端工程 毫无疑问,搭建一个项目的框架,那第一步肯定是得创建一个工程啦.cmd命令,输入vu ...

  9. vue+node.js手把手教你搭建一个直播平台(二)

    上一期,帅气的小羽给老铁们介绍了直播平台的项目的后端搭建,这期就让小羽带大家来搭建一下前端的框架. 1.创建前端工程 毫无疑问,搭建一个项目的框架,那第一步肯定是得创建一个工程啦.cmd命令,输入vu ...

最新文章

  1. win7发现不了无线网络_win10系统间设置共享文件夹后“网络”选项下仍然无任何文件(即发现不了共享电脑)...
  2. 第九步:仓库管理(成品)
  3. 机器学习之 weka学习(四)
  4. 计算机英语课程背景,专家讲座第十五讲:信息化背景下高质量大学英语课程建设与教学设计...
  5. [渝粤教育] 西南科技大学 英美文学 在线考试复习资料
  6. java实验金额转换_java 数字金额转换中文金额
  7. python 线性规划问题_一学高数,线代就头疼?让python帮你解决(内含教程)
  8. Docker常用命令,这些都要会!
  9. 运维安全加固规范_DBA如何巧用“三十六计”保障数据库安全?
  10. 人工智能技术与计算机科学区别,智能科学与技术与人工智能的区别
  11. 第十届“泰迪杯“感谢学习总结(国三附源码)
  12. ios 改变图片尺寸_iOS 修改图片尺寸的方法
  13. 对C标准中空白字符(空格、回车符(\r)、换行符(\n)、水平制表符(\t)、垂直制表符(\v)、换页符(\f))的理解
  14. TCon 2012之分布式系统测试实践
  15. Python自动化测试详解
  16. 如何编制试算平衡表_在实际工作中,余额试算平衡通过编制试算平衡表进行。()...
  17. 再度盈利,搜狐稳了?
  18. EXCEL2016学生表两列名字按相同排序,对比期中期末考试选出进步学生
  19. 市面上有哪几种门_卧室门怎么选?市面上5种常见房门大揭秘
  20. 给网赚从业者的几点建议

热门文章

  1. 随机加密_随机艺术和加密圣诞树
  2. linux系统部署war包,查看tomcat日志
  3. 【CTSC2017】【BZOJ4903】吉夫特 卢卡斯定理 DP
  4. Linux多命令协作:管道及重定向
  5. python3.5中import sqlite3报错:ImportError: No module named _sqlite3
  6. 【python】os.getcwd和getcwdu
  7. PHP的curl实现get,post 和 cookie(几个实例)
  8. js实现同时提交多个表单
  9. cocos2d-x 学习资料(很全)
  10. NDoc修改版,支持中文注释及中文界面。