JavaScript数据结构——链表

链表:存储有序的元素集合,但不同于数组,链表中的元素在内存中不是连续放置的。每个元素由一个存储元素本身的节点和一个指向下一个元素的引用(也称指针或链接)组成。

好处:可以添加或移除任意项,它会按需扩容,且不需要移动其他元素。

与数组的区别:

数组:可以直接访问任何位置的任何元素;

链表:想要访问链表中的一个元素,需要从起点(表头)开始迭代列表直到找到所需的元素。

现实案例:康佳舞队、寻宝游戏

单向链表:一个节点只有链向下一个节点的链接;

双向链表:链接是双向的,一个链向下一个元素,另一个链向前一个元素

优点:双向链表提供了两种迭代列表的方法:从头到尾,或者反过来。我们也可以访问一个特定节点的下一个或前一个元素。在单向链表中,如果迭代列表时错过了要找的元素,就需要回到列表起点,重新开始迭代。

-------------------------------------------------------------------------------------------------------------

链表方法声明:

1. 定义Node辅助类;

2. 内部属性 length;

2. 存储第一个节点(head)的引用


序号

方法

说明

1
append(element) 向列表尾部添加一个新的项

2
insert(position, element) 向列表的特定位置插入一个新的项

3

remove(element)
从列表中移除一项

4

indexOf (element )
返回元素在列表中的索引。如果列表中没有该元素则返回-1

5
removeAt(position)
从列表的特定位置移除一项

6

isEmpty()

如果链表中不包含任何元素,返回 true,如果链表长度大于 0 则返回 false

7

size ( )
返回链表包含元素个数。与数组的 length 属性类似

8

toString ( )
由于列表项使用了 Node 类,就需要重写继承自 JavaScript 对象默认的 toString 方法,让其只输出元素的值

链表实现:

  1 function LinkedList() {
  2     // 定义辅助类Node
  3     var Node = function(element) {
  4         this.element = element;    // element属性,即要添加到列表的元素
  5         this.next = null;    // next属性,即指向列表中下一个节点项的指针
  6     }
  7
  8     var length = 0;    // 内部属性/私有变量
  9     var head = null;    // 第一个节点的引用
 10
 11     // 方法
 12     this.append = function(element) {
 13         var node = new Node(element),    // 把element作为值传入,创建Node项
 14             current;
 15
 16         if (head === null) {    // 列表中第一个节点,如果head元素为null,则意味着向列表添加第一个元素
 17             head = node;    // head指向node元素,下一个node将会自动生成null
 18         } else {
 19             current = head;
 20
 21             // 循环列表,直到找到最后一项
 22             while(current.next) {
 23                 current = current.next;
 24             }
 25
 26             // 找到最后一项,将其next赋为node,建立连接
 27             current.next = node;    // 列表中最后一个节点的下一个元素始终是null
 28         }
 29
 30         length++;    // 更新链表长度,这样就能控制它,轻松地得到列表的长度
 31     };
 32
 33     this.insert = function(position, element) {
 34         // 检查越界值
 35         if (position >= 0 && position <= length) {
 36             var node = new Node(element),
 37                 current = head,
 38                 previous,
 39                 index = 0;
 40
 41             if (position === 0) {    // 在第一个位置添加
 42                 node.next = current;
 43                 head = node;
 44             } else {
 45                 while (index++ < position) {
 46                     previous = current;
 47                     current = current.next;
 48                 }
 49                 node.next = current;
 50                 previous.next = node;
 51             }
 52
 53             length++;
 54
 55             return true;
 56
 57         } else {
 58             return false;
 59         }
 60     };
 61
 62     this.removeAt = function(position) {
 63         // 检查越界值
 64         if (position > -1 && position < length) {
 65             var current = head,    // current变量总是为对所循环列表的当前元素的引用
 66                 previous,    // previous变量为对当前元素的前一个元素的引用
 67                 index = 0;
 68
 69             // 移除第一项
 70             if (position === 0) {
 71                 head = current.next;
 72             } else {
 73                 while (index++ < position) {    // 使用用于内部控制和递增的index变量来迭代列表
 74                     previous = current;
 75                     current = current.next;
 76                 }
 77
 78                 // 将previous与current的下一项链接起来:跳过current,从而移除它
 79                 previous.next = current.next;
 80             }
 81
 82             length--;
 83
 84             return current.element;
 85         } else {
 86             return null;
 87         }
 88     };
 89
 90     this.remove = function(element) {
 91         var index = this.indexOf(element);
 92         return this.removeAt(index);
 93     };
 94
 95     this.indexOf = function(element) {
 96         var current = head,
 97             index = -1;
 98
 99         while (current) {
100             if (element === current.element) {
101                 return index;
102             }
103             index++;
104             current = current.next;
105         }
106
107         return -1;
108     };
109
110     this.isEmpty = function() {
111         return length === 0;
112     };
113
114     this.size = function() {
115         return length;
116     };
117
118     this.toString = function() {
119         var current = head,
120             string = ‘‘;
121
122         while (current) {
123             string += current.element;
124             current = current.next;
125         }
126
127         return string;
128     };
129
130     this.getHead = function () {
131         return head;
132     };
133 }

LinkedList

双向链表实现:

 1 function DoublyLinkedList() {
 2     var Node = function(element) {
 3         this.element = element;
 4         this.next = null;
 5         this.prev = null;
 6     };
 7
 8     var length = 0;
 9     var head = null;
10     var tail = null;    // 新增的
11
12     // 方法
13     this.insert = function(position, element) {
14         // 检查越界值
15         if (position >= 0 && position <= length) {
16             var node = new Node(element),
17                 current = head,
18                 previous,
19                 index = 0;
20
21             if (position === 0) {    // 在第一个位置添加
22                 if (!head) {    // 新增的
23                     head = node;
24                     tail = node;
25                 } else {
26                     node.next = current;
27                     current.prev = node;
28                     head = node;
29                 }
30             } else if (position === length-1) {    // 最后一项 //新增的
31                 current = tail;
32                 current.next = node;
33                 node.prev = current;
34                 tail = node;
35             } else {
36                 while (index++ < position) {
37                     previous = current;
38                     previous.next = node;
39                 }
40
41                 node.next = current;
42                 previous.next = node;
43
44                 current.prev = node;    //新增的
45                 node.prev = previous;    //新增的
46             }
47
48             length++;
49             return true;
50
51         } else {
52             return false;
53         }
54     };
55
56     this.removeAt = function(position) {
57         // 检查越界值
58         if (position > -1 && position < length) {
59             var current = head,
60                 previous,
61                 index = 0;
62
63             // 移除第一项
64             if (position === 0) {
65                 head = current.next;
66
67                 // 如果只有一项,更新tail //新增的
68                 if (length === 1) {
69                     tail = null;
70                 } else {
71                     head.prev = null;
72                 }
73             } else if (position === length-1) {
74                 current = tail;
75                 tail = current.prev;
76                 tail.next = null;
77             } else {
78                 while (index++ < position) {
79                     previous = current;
80                     current = current.next;
81                 }
82                 // 将prvious与current的下一项链接起来——跳过current
83                 previous.next = current.next;
84                 current.next.prev = previous;    // 新增的
85             }
86
87             length--;
88
89             return current.element;
90         } else {
91             return null;
92         }
93     };
94 }

DoublyLinkedList

时间: 2024-08-08 21:17:46

JavaScript数据结构——链表的相关文章

JavaScript数据结构——链表的实现

前面楼主分别讨论了数据结构栈与队列的实现,当时所用的数据结构都是用的数组来进行实现,但是数组有的时候并不是最佳的数据结构,比如在数组中新增删除元素的时候需要将其他元素进行移动,而在javascript中使用spit()方法不需要访问其他元素.如果你在使用数组的时候发现很慢,就可以考虑使用链表. 链表的概念 链表是一种常见的数据结构.它是动态地进行存储分配的一种结构.链表有一个"头指针"变量,以head表示,它存放一个地址,指向一个元素.每个结点都使用一个对象的引用指标它的后继,指向另一

javascript数据结构-链表

gihtub博客地址 链表 是一种物理存储单元上非连续.非顺序的存储结构,它既可以表示线性结构,也可以用于表示非线性结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的.链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成.每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域. function LinkedList() { function Node(element) { this.element = element; this.nex

数据结构与算法JavaScript (三) 链表

数据结构与算法JavaScript (三) 链表 我们可以看到在javascript概念中的队列与栈都是一种特殊的线性表的结构,也是一种比较简单的基于数组的顺序存储结构.由于 javascript的解释器针对数组都做了直接的优化,不会存在在很多编程语言中数组固定长度的问题(当数组填满后再添加就比较困难了,包括添加删除, 都是需要把数组中所有的元素全部都变换位置的,javascript的的数组确实直接给优化好了,如 push,pop,shift,unshift,split方法等等…) 线性表的顺序

重读《学习JavaScript数据结构与算法-第三版》- 第6章 链表(一)

定场诗 伤情最是晚凉天,憔悴厮人不堪言: 邀酒摧肠三杯醉.寻香惊梦五更寒. 钗头凤斜卿有泪,荼蘼花了我无缘: 小楼寂寞新雨月.也难如钩也难圆. 前言 本章为重读<学习JavaScript数据结构与算法>的系列文章,该章节主要讲述数据结构-链表,以及实现链表的过程和原理. 链表 链表,为什么要有这种数据结构呢?当然,事出必有因! 数组-最常用.最方便的数据结构,But,当我们从数组的起点或中间插入或移动项的成本很高,因为我们需要移动数组元素. 链表,是存储有序的元素集合.链表中的元素在内存中并不

JavaScript数据结构——队列的实现

前面楼主简单介绍了JavaScript数据结构栈的实现,http://www.cnblogs.com/qq503665965/p/6537894.html,本次将介绍队列的实现. 队列是一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和栈一样,队列是一种操作受限制的线性表.进行插入操作的端称为队尾,进行删除操作的端称为队头. 队列的两种主要操作是:向队列中插入新元素和删除队列中的元素.插入操作也叫做入队,删除操作也叫做出队.入队操

JavaScript数据结构——树

树:非顺序数据结构,对于存储需要快速查找的数据非常有用. 二叉树:二叉树中的节点最多只能有两个子节点(左侧子节点和右侧子节点).这些定义有助于我们写出更高效的向/从树中插入.查找和删除节点的算法. 二叉搜索树:二叉树的一种,但是它只允许你在左侧节点存储(比父节点)小的值,在右侧节点存储(比父节点)大/等于的值. 遍历一棵树:是指访问树的每个节点并对它们进行某种操作的过程.访问树的所有节点有三种方式:中序.先序和后序. 中序遍历:是一种以上行顺序访问 BST 所有节点的的遍历方式,也就是以从最小到

javascript数据结构和算法 零(前记+序言)

前记 这本书Data Structure and Algorithm with Javascript 我将其翻译成<< javascript 数据结构和算法>> 为什么这么翻译?而不是翻译成"用javascript实现数据结构和算法" 原因有二: 一个,我觉的它更加简洁,第二个,我是想强调我们在这里使用的是javascript. 我不喜欢一些翻译的人把一个简单的语句进行加工,搞得晦涩难懂.我更喜欢外国人写书的 那种原汁原味.同样,我很喜欢外国人的那种分享精神,它

javascript数据结构和算法 一(本书组织结构)

环境 我们在本书中使用的Javascript编程环境是基于SpiderMonkey 引擎的javascript shell. 第一章讲述了在你的环境中下载 shell的介绍. 其他的shell例如Nodejs同样可以工作,虽然你可能需要简单的改变下代码. 除了shell,唯一你要准备的就是文本编辑器. 本书的组织结构 第一章:javascript语言的概览,至少是在本书中使用的javascript的一些特征.这一章同时展示了在整本书中使用的一些编程风格. 第二章:讨论了在计算机科学中最通用的数据

JavaScript数据结构——图的实现

在计算机科学中,图是一种网络结构的抽象模型,它是一组由边连接的顶点组成.一个图G = (V, E)由以下元素组成: V:一组顶点 E:一组边,连接V中的顶点 下图表示了一个图的结构: 在介绍如何用JavaScript实现图之前,我们先介绍一些和图相关的术语. 如上图所示,由一条边连接在一起的顶点称为相邻顶点,A和B是相邻顶点,A和D是相邻顶点,A和C是相邻顶点......A和E是不相邻顶点.一个顶点的度是其相邻顶点的数量,A和其它三个顶点相连,所以A的度为3,E和其它两个顶点相连,所以E的度为2