在使用C++的时候我们经常会使用到各种容器,这些容器其实就是一种数据结构。在java中其实也是如此。但是由于javascript只给我们提供了一种内置的数据结构数组,准备来说是对象。没有我们常见的那些数据结构,但是在实际的工作中我们却不能离开这些常见的数据结构。所以我们只能去自己构造了。

虽然javascript中的数组的操作,比C++/java等操作数组方便的多,但是毕竟数组是一种对象,在对数据进行处理的时候效率还是很低的。所以有时候我们要自己构造想要的数据结构了。

定义(define):

链表是有一组节点组成的集合。每个节点都包含两部分:第一部分是存储数据元素的数据域,另一个是存储下一个结点地址的引用域。每个节点都会使用一个对象的引用来指向他的后继节点。这个对后继对象的引用就是我们常说的链。由于不必须按顺序存储,链表在插入的时候可以达到O(1)的复杂度,比另一种线性表顺序表快得多,但是查找一个节点或者访问特定编号的节点则需要O(n)的时间,而线性表和顺序表相应的时间复杂度分别是O(logn)和O(1)。因此在除了对数据元素的随机访问使用数组外,其他情况下在使用一位数组的地方,都可以使用链表。

我们知道数组主要是靠位置来进行引用元素的,而链表则是通过彼此之间的关系来引用的。在我们想查找一个再链表中的元素的时候,我们就必须从链表头开始遍历查找。然而在标示链表头的时候确实有些麻烦,利用javascript的灵活性,我想我们还是很容易就解决的。从上图中我们也看到最后一个元素的引用应该设置为null。由于在链表中插入禾删除元素,只需要改变自身元素与相邻元素的引用就可以了,不必像数组那样移动元素的位置,这样看起来效率会高一点。

构建链表(construct linked list):

我们设计的这个链表是一个基于对象的链表,包括两个类:Node类用来表示节点,LinkedList类用来提供插入节点,删除节点,查询节点元素个数。。等一些列操作。

Node类:

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

Node类包含两个属性,element用来保存节点的元素,next用来保存指向下一个节点的链接。head节点的next属性我们暂且设置为null,当有数据插入的时候我们在设置head的next属性指向这个新元素。

LinkedList类:

LinkedList类和Node类一样也是一个构造函数,但LinkListed类只有一个属性,那就是使用一个Node节点来保存该链表的头节点。

<html>
<head>
<title>Date Example</title>
</head>
<body>
<div id="content"></div>
<input type="button" value="Set InnerHTML" onclick="testDate()"> <script type="text/javascript"> // Node construct
function Node (element){
this.element = element;
this.next = null;
} // LinkedList construct
function LinkedList (){
this.head = new Node("head"); // 遍历链表查找给定的数据(我们要把数据插入到那个节点的后面)
this.find = function (item){
var currNode = this.head;
while (currNode.element != item){
currNode = currNode.next;
} return currNode
}; // 向链表中插入一个节点
this.insert = function (newElem, item){
var newNode = new Node(newElem);
var current = this.find(item);
newNode.next = current.next;
current.next = newNode;
}; // 查询前一个节点
this.findPrevious = function (item){
var currNode = this.head;
while ((currNode.next != null) && (currNode.next.element != item)){
currNode = currNode.next;
}
return currNode;
}; // 删除某个节点
this.remove = function (item){
var prevNode = this.findPrevious(item);
if (prevNode.next != null){ prevNode.next = prevNode.next.next;
}
}; // 显示列表中的节点
this.display = function (){
var currNode = this.head;
while (currNode.next != null){
console.log("current Node is:" + currNode.next.element);
currNode = currNode.next;
}
}; }
</script>
</body>
</html>

上面就是一个比较构造一个普通链表的方式。里面包含了基本的链表操作方法。

var cities = new LinkedList();
cities.insert("shang", "head");
cities.insert("hai", "shang");
cities.insert("shan", "hai");
cities.insert("xi", "shan");
cities.display();

在浏览器的Cnsole中查看结果。

链表在日常 使用中还有双向链表,循环链表。。。

首先来看一下双向链表吧:

在上面创建的链表中我们只能从链表的头遍历到链表的尾,二双向链表让我们既能从链表的头遍历到尾,也能让我们从尾遍历到头。其实很简单,我们在每个节点中增加一个属性,这个属性指向前驱节点的链接,这样只是给插入与删除节点多添加一些代码罢了。如图:

展示了双向链表的工作原理。

<html>
<head>
<title>Date Example</title>
</head>
<body>
<div id="content"></div>
<input type="button" value="Set InnerHTML" onclick="testDate()"> <script type="text/javascript"> // Node construct
function Node (element){
this.element = element;
this.next = null;
this.previous = null; } // LinkedList construct
function LinkedList (){
this.head = new Node("head"); // 遍历链表查找给定的数据(我们要把数据插入到那个节点的后面)
this.find = function (item){
var currNode = this.head;
while (currNode.element != item){
currNode = currNode.next;
} return currNode
}; // 向链表中插入一个节点
this.insert = function (newElem, item){
var newNode = new Node(newElem);
var current = this.find(item);
newNode.next = current.next;
newNode.previous = current;
current.next = newNode;
}; // 查找最后一个节点(便于我们从后往前遍历)
this.findLast = function (){
var lastNode = this.head;
while (lastNode.next != null){
lastNode = lastNode.next;
} return lastNode;
}; // 反序显示双向列表中的元素
this.displayReverse = function (){
var currNode = this.head;
currNode = this.findLast();
while (currNode.previous != null){
console.log("current Node is:" + currNode);
currNode = currNode.previous;
}
}; // 删除某个节点
this.remove = function (item){
var crrNode = this.find(item);
if (crrNode.next != null){ currNode.previous.next = currNode.next;
currNode.next.previous = currNode.preious;
currNode.previous = null;
currNode.next = null;
}
}; // 显示列表中的节点
this.display = function (){
var currNode = this.head;
while (currNode.next != null){
console.log("current Node is:" + currNode.next.element);
currNode = currNode.next;
}
}; } var cities = new LinkedList();
cities.insert("shang", "head");
cities.insert("hai", "shang");
cities.insert("shan", "hai");
cities.insert("xi", "shan");
cities.display(); </script>
</body>
</html>

循环列表:

循环链表是另一种形式的链式存贮结构。它的特点是表中最后一个结点的引用指向头节点,整个链表形成一个环

从链表的尾部向后移动,将会从新遍历这个链表。

<html>
<head>
<title>Date Example</title>
</head>
<body>
<div id="content"></div>
<input type="button" value="Set InnerHTML" onclick="testDate()"> <script type="text/javascript"> // Node construct
function Node (element){
this.element = element;
this.next = null;
} // LinkedList construct
function LinkedList (){
this.head = new Node("head");
this.head.next = this.head; // 遍历链表查找给定的数据(我们要把数据插入到那个节点的后面)
this.find = function (item){
var currNode = this.head;
while ((currNode.element != item) && (currNode.next.element != "head")){
currNode = currNode.next;
} return currNode
}; // 向链表中插入一个节点
this.insert = function (newElem, item){
var newNode = new Node(newElem);
var current = this.find(item);
newNode.next = current.next;
current.next = newNode;
}; // 查询前一个节点
this.findPrevious = function (item){
var currNode = this.head;
while ((currNode.next != null) && (currNode.next.element != item) && (currNode.next.element != "head")){
currNode = currNode.next;
}
return currNode;
}; // 删除某个节点
this.remove = function (item){
var prevNode = this.findPrevious(item);
if (prevNode.next != null){ prevNode.next = prevNode.next.next;
}
}; // 显示列表中的节点
this.display = function (){
var currNode = this.head;
while ((currNode.next != null) && (currNode.next.element != "head")){
console.log("current Node is:" + currNode.next.element);
currNode = currNode.next;
}
}; } var cities = new LinkedList();
cities.insert("shang", "head");
cities.insert("hai", "shang");
cities.insert("shan", "hai");
cities.insert("xi", "shan");
cities.display(); </script>
</body>
</html>

当我们在使用循环链表的时候,注意不要使程序陷入死循环。。。在以前这些方法的基础上我们还可以编写更多的方法,来简化我们的使用和操作。

javascript linkedlist data structures的更多相关文章

  1. javascript Set data structures

    集合(set)是一组无序的,但彼此之间又有一定相关性的数据集.每个成员在数组中只能出现一次. 在使用集合(set)之前最好先理解一下内容: 1.不包含任何成员的集合称为空集合. 2.如果两个集合的成员 ...

  2. javascript Dictionary data structures

    Dictionary常被称为数据字典,是一种用来保存键值对的数据结构,比如我们日常的电话本,就是一个Dictionary.我们通过键(名字),就可以访问到对应的值(电话号码).在C++与java中我们 ...

  3. JavaScript data types and data structures

    JavaScript data types and data structures Programming languages all have built-in data structures, b ...

  4. [Javascript] Avoiding Mutations in JavaScript with Immutable Data Structures

    To demonstrate the difference between mutability and immutability, imagine taking a drink from a gla ...

  5. The Swiss Army Knife of Data Structures … in C#

    "I worked up a full implementation as well but I decided that it was too complicated to post in ...

  6. Go Data Structures: Interfaces

    refer:http://research.swtch.com/interfaces Go Data Structures: Interfaces Posted on Tuesday, Decembe ...

  7. A library of generic data structures

    A library of generic data structures including a list, array, hashtable, deque etc.. https://github. ...

  8. 剪短的python数据结构和算法的书《Data Structures and Algorithms Using Python》

    按书上练习完,就可以知道日常的用处啦 #!/usr/bin/env python # -*- coding: utf-8 -*- # learn <<Problem Solving wit ...

  9. Persistent Data Structures

    原文链接:http://www.codeproject.com/Articles/9680/Persistent-Data-Structures Introduction When you hear ...

随机推荐

  1. 解决Sublime包管理package control 报错 There are no packages available for installation

    解决Sublime包管理package control 报错 There are no packages available for installation 真的是哔了狗了,要不是我机智的重新安装了 ...

  2. [HTML5] Avoiding CSS Conflicts via Shadow DOM CSS encapsulation

    Shadow DOM is part of the web components specification. It allows us to ship self contained componen ...

  3. 修复损坏的 shapefile

    一.SHP文件 Shapefile文件(简称SHP)作为ESRI一种经典的数据格式,被很多其他软件所支持,如CAD.MapGIS等,虽然也有一些限制(如无法进行拓扑分析.字段长度为10个字符等),但其 ...

  4. Linux c 管道文件-进程间的通信 mkfifo、pipe

    管道文件: 1.       创建管道mkfifo(命名管道) #include<sys/stat.h> int mkfifo( const  char  *pathname, mode_ ...

  5. SQL:1999基本语法(学习笔记)

    SQL:1999基本语法 SELECT [DISTINCT] * | 列名称 [AS]别名,........ FROM 表名称1 [别名1][CROSS JOIN表名称2 别名2]| [NATURAL ...

  6. 应用程序正常初始化(0xc0000135)失败的解决方法

    转自:http://blog.sina.com.cn/s/blog_64fba4e00100mzf9.html 这是由于没有安装.NET framework 所造成的,请安装.NET framewor ...

  7. oracl 、mysql在线查看文档

    Oracle .mysql在线开发文档: http://www.runoob.com/sql/sql-union.html

  8. 批量上传插件(flash,html5,jquery)

    1.jQuery File Upload 官网:http://blueimp.github.com/jQuery-File-Upload/ 在线示例:http://blueimp.github.com ...

  9. 栈溢出笔记1.3 准备Shellcode

    经过1.1和1.2节的讲述,我们已经知道了怎样更改EIP的值. 程序运行函数之后将跳转到我们设定的位置開始运行,因此,我们须要准备一个自己的程序,接手后面的工作.这是一个什么样的程序?是一个C语言编写 ...

  10. jquery局部打印插件使用

    基于jquery库的jquery.PrintArea.js插件源代码为: (function ($) { var printAreaCount = 0; $.fn.printArea = functi ...