JavaScript数据结构之链表的实现


Posted in Javascript onMarch 19, 2017

前面楼主分别讨论了数据结构栈与队列的实现,当时所用的数据结构都是用的数组来进行实现,但是数组有的时候并不是最佳的数据结构,比如在数组中新增删除元素的时候需要将其他元素进行移动,而在javascript中使用spit()方法不需要访问其他元素。如果你在使用数组的时候发现很慢,就可以考虑使用链表。

链表的概念

链表是一种常见的数据结构。它是动态地进行存储分配的一种结构。链表有一个“头指针”变量,以head表示,它存放一个地址,指向一个元素。每个结点都使用一个对象的引用指标它的后继,指向另一个结点的引用叫做链。

JavaScript数据结构之链表的实现

数组元素依靠下标(位置)来进行引用,而链表元素则是靠相互之间的关系来进行引用。因此链表的插入效率很高,下图演示了链表结点d的插入过程: 

 JavaScript数据结构之链表的实现

删除过程:

JavaScript数据结构之链表的实现

基于对象的链表

我们定义2个类,Node类与LinkedList类,Node为结点数据,LinkedList保存操作链表的方法。

首先看Node类:

function Node(element){
  this.element = element;
   this.next = null;
 }

element用来保存结点上的数据,next用来保存指向一下结点的的链接。

LinkedList类:

function LinkedList(){
     this.head = new Node('head');
     this.find = find;
     this.insert = insert;
     this.remove = remove;
     this.show = show;
}

find()方法,从头结点开始,沿着链表结点一直查找,直到找到与item内容相等的element则返回该结点,没找到则返回空。

function find(item){
     var currentNode = this.head;//从头结点开始
     while(currentNode.element!=item){
         currentNode = currentNode.next;
     }
     return currentNode;//找到返回结点数据,没找到返回null
}

Insert方法。通过前面元素插入的演示可以看出,实现插入简单四步:

1、创建结点

2、找到目标结点

3、修改目标结点的next指向链接

4、将目标结点的next值赋值给要插入的结点的next

function insert(newElement,item){
     var newNode = new Node(newElement);
     var currentNode = this.find(item);
     newNode.next = currentNode.next;
     currentNode.next = newNode;
 }

Remove()方法。删除某一节点需要先找到被删除结点的前结点,为此我们定义方法frontNode():

function frontNode(item){
     var currentNode = this.head;
     while(currentNode.next.element!=item&¤tNode.next!=null){
         currentNode = currentNode.next;
     }   
     return currentNode;
}

简答三步:

1、创建结点

2、找到目标结点的前结点

3、修改前结点的next指向被删除结点的n后一个结点

function remove(item){
     var frontNode = this.frontNode(item);
     //console.log(frontNode.element);
     frontNode.next = frontNode.next.next;
 }

Show()方法:

function show(){
     var currentNode = this.head,result;
     while(currentNode.next!=null){
         result += currentNode.next.element;//为了不显示head结点
         currentNode = currentNode.next;
     }
}

测试程序:

var list = new LinkedList();
list.insert("a","head");
list.insert("b","a");
list.insert("c","b");
console.log(list.show());
list.remove("b");
console.log(list.show());

输出:

JavaScript数据结构之链表的实现

双向链表

从链表的头节点遍历到尾节点很简单,但有的时候,我们需要从后向前遍。此时我们可以通过给 Node 对象增加一个属性,该属性存储指向前驱节点的链接。楼主用下图来双向链表的工作原理。

JavaScript数据结构之链表的实现

首先我们先给Node类增加front属性:

function Node(element){
  this.element = element;
  this.next = null;
   this.front = null;
 }

当然,对应的insert()方法和remove()方法我们也需要做相应的修改: 

function insert(newElement,item){
  var newNode = new Node(newElement);
  var currentNode = this.find(item);
  newNode.next = currentNode.next;
  newNode.front = currentNode;//增加front指向前驱结点
  currentNode.next = newNode;
}
function remove(item){  
  var currentNode = this.find(item);//找到需要删除的节点
  if (currentNode.next != null) {
    currentNode.front.next = currentNode.next;//让前驱节点指向需要删除的节点的下一个节点
    currentNode.next.front = currentNode.front;//让后继节点指向需要删除的节点的上一个节点
    currentNode.next = null;//并设置前驱与后继的指向为空
    currentNode.front = null;    
  }  
}

反序显示链表:

需要给双向链表增加一个方法,用来查找最后的节点。 findLast() 方法找出了链表中的最后一个节点,可以免除从前往后遍历链。

function findLast() {//查找链表的最后一个节点
  var currentNode = this.head;
  while (currentNode.next != null) {
    currentNode = currentNode.next;
  }
  return currentNode;
}

实现反序输出:

function showReverse() {
  var currentNode = this.head, result = "";
  currentNode = this.findLast(); 
  while(currentNode.front!=null){
    result += currentNode.element + " ";
    currentNode = currentNode.front;
  }
  return result;
}

测试程序:

var list = new LinkedList();
list.insert("a","head");
list.insert("b","a");
list.insert("c","b");
console.log(list);
list.remove("b");
console.log(list.show());
console.log(list.showReverse());

输出:

JavaScript数据结构之链表的实现

循环链表

循环链表是另一种形式的链式存贮结构。它的特点是表中最后一个结点的指针域指向头结点,整个链表形成一个环。循环链表和单向链表相似,节点类型都是一样的。唯一的区别是,在创建循环链表时,让其头节点的 next 属性指向它本身,即:

head.next = head

这种行为会传导至链表中的每个节点,使得每个节点的 next 属性都指向链表的头节点。楼主用下图来表示循环链表:

JavaScript数据结构之链表的实现

修改构造方法:

function LinkedList(){
  this.head = new Node('head');//初始化
  this.head.next = this.head;//直接将头节点的next指向头节点形成循环链表
  this.find = find;
  this.frontNode = frontNode;
  this.insert = insert;
  this.remove = remove;
  this.show = show; 
}

这时需要注意链表的输出方法show()与find()方法,原来的方式在循环链表里会陷入死循环,while循环的循环条件需要修改为当循环到头节点时退出循环。

function find(item){
  var currentNode = this.head;//从头结点开始
  while(currentNode.element!=item&¤tNode.next.element!='head'){
    currentNode = currentNode.next;
  }
  return currentNode;//找到返回结点数据,没找到返回null
}
function show(){
  var currentNode = this.head,result = "";
  while (currentNode.next != null && currentNode.next.element != "head") {   
    result += currentNode.next.element + " ";
    currentNode = currentNode.next;
  }
  return result;
}

测试程序:

var list = new LinkedList();
list.insert("a","head");
list.insert("b","a");
list.insert("c","b");
console.log(list.show());
list.remove("b");
console.log(list.show());

测试结果:

JavaScript数据结构之链表的实现

本文用到的示例代码地址:https://github.com/LJunChina/JavaScript

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持三水点靠木!

Javascript 相关文章推荐
jQuery Flash/MP3/Video多媒体插件
Jan 18 Javascript
jquery 锁定弹出层实现代码
Feb 23 Javascript
火狐textarea输入法的bug的触发及解决
Jul 24 Javascript
jquery中获取id值方法小结
Sep 22 Javascript
js模拟点击以提交表单为例兼容主流浏览器
Nov 29 Javascript
Iframe实现跨浏览器自适应高度解决方法
Sep 02 Javascript
JavaScript中的类(Class)详细介绍
Dec 30 Javascript
jQuery+PHP星级评分实现方法
Oct 02 Javascript
ClearTimeout消除闪动实例代码
Feb 29 Javascript
javascript中href和replace的比较(详解)
Nov 25 Javascript
AngularJS 的$timeout服务示例代码
Sep 21 Javascript
vue3.0 CLI - 1 - npm 安装与初始化的入门教程
Sep 14 Javascript
用jQuery实现圆点图片轮播效果
Mar 19 #Javascript
Bootstrap 网格系统布局详解
Mar 19 #Javascript
用JavaScript和jQuery实现瀑布流
Mar 19 #Javascript
JSONP基础知识详解
Mar 19 #Javascript
jQuery中table数据的值拷贝和拆分
Mar 19 #Javascript
js实现旋转木马效果
Mar 17 #Javascript
jQuery实现验证码功能
Mar 17 #Javascript
You might like
PHP中iconv函数转码时截断字符问题的解决方法
2015/01/21 PHP
PHP基于array_unique实现二维数组去重
2020/07/14 PHP
JS实现浏览器菜单命令
2006/09/05 Javascript
JavaScript 特殊字符
2007/04/05 Javascript
比较全的JS checkbox全选、取消全选、删除功能代码
2008/12/19 Javascript
JavaScript 类的定义和引用 JavaScript高级培训 自定义对象
2010/04/27 Javascript
缓动函数requestAnimationFrame 更好的实现浏览器经动画
2012/12/07 Javascript
十个迅速提升JQuery性能让你的JQuery跑得更快
2012/12/10 Javascript
DWZ刷新dialog解决方法
2013/03/03 Javascript
js关于精确计算和数值格式化以及直接引js文件
2014/01/28 Javascript
浅谈javascript语法和定时函数
2015/05/03 Javascript
微信企业号开发之微信考勤百度地图定位
2015/09/11 Javascript
整理Javascript基础语法学习笔记
2015/11/29 Javascript
AngularJs学习第五篇从Controller控制器谈谈$scope作用域
2016/06/08 Javascript
基于JS实现弹出一个隐藏的div窗口body页面变成灰色并且不可被编辑
2016/12/14 Javascript
微信小程序 刷新上拉下拉不会断详细介绍
2017/05/11 Javascript
knockoutjs模板实现树形结构列表
2017/07/31 Javascript
清空元素html("") innerHTML="" 与 empty()的区别和应用(推荐)
2017/08/14 Javascript
js实现网页的两个input标签内的数值加减(示例代码)
2017/08/15 Javascript
微信小程序模版渲染详解
2018/01/26 Javascript
vue 弹框产生的滚动穿透问题的解决
2018/09/21 Javascript
JS/HTML5游戏常用算法之路径搜索算法 随机迷宫算法详解【普里姆算法】
2018/12/13 Javascript
Vue 组件的挂载与父子组件的传值实例
2020/09/02 Javascript
让python json encode datetime类型
2010/12/28 Python
Django框架模板语言实例小结【变量,标签,过滤器,继承,html转义】
2019/05/23 Python
Python TKinter如何自动关闭主窗口
2020/02/26 Python
美国领先的在线旅游网站:Orbitz
2018/11/05 全球购物
2014年五四青年节活动策划书
2014/04/22 职场文书
创建文明城市倡议书
2015/04/28 职场文书
院系推荐意见
2015/06/05 职场文书
2016党员党章学习心得体会
2016/01/14 职场文书
财产分割协议书
2016/03/22 职场文书
施工安全责任协议书
2016/03/23 职场文书
2016年党员公开承诺书范文
2016/03/24 职场文书
同学聚会开幕词
2019/04/02 职场文书
Java存储没有重复元素的数组
2022/04/29 Java/Android