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     // 向列表的特定位置插入一个新的项
 34     this.insert = function(position, element) {
 35         // 检查越界值
 36         if (position >= 0 && position <= length) {
 37             var node = new Node(element),
 38                 current = head,
 39                 previous,
 40                 index = 0;
 41 
 42             if (position === 0) {    // 在第一个位置添加
 43                 node.next = current;
 44                 head = node;
 45             } else {
 46                 while (index++ < position) {
 47                     previous = current;
 48                     current = current.next;
 49                 }
 50                 node.next = current;
 51                 previous.next = node;
 52             }
 53 
 54             length++;
 55 
 56             return true;
 57 
 58         } else {
 59             return false;
 60         }
 61     };
 62 
 63     // 从列表的特定位置移除一项
 64     this.removeAt = function(position) {
 65         // 检查越界值
 66         if (position > -1 && position < length) {
 67             var current = head,    // current变量总是为对所循环列表的当前元素的引用
 68                 previous,    // previous变量为对当前元素的前一个元素的引用
 69                 index = 0;
 70 
 71             // 移除第一项
 72             if (position === 0) {
 73                 head = current.next;
 74             } else {
 75                 while (index++ < position) {    // 使用用于内部控制和递增的index变量来迭代列表
 76                     previous = current;    
 77                     current = current.next;
 78                 }
 79 
 80                 // 将previous与current的下一项链接起来:跳过current,从而移除它
 81                 previous.next = current.next;
 82             }
 83 
 84             length--;
 85 
 86             return current.element;
 87         } else {
 88             return null;
 89         }
 90     };
 91 
 92     // 从列表中移除一项
 93     this.remove = function(element) {
 94         var index = this.indexOf(element);
 95         return this.removeAt(index);
 96     };
 97 
 98     // 返回元素在列表中的索引。如果列表中没有该元素则返回-1
 99     this.indexOf = function(element) {
100         var current = head,
101             index = -1;
102 
103         while (current) {
104             if (element === current.element) {
105                 return index;
106             }
107             index++;
108             current = current.next;
109         }
110 
111         return -1;
112     };
113 
114     // 如果链表中不包含任何元素,返回 true,如果链表长度大于 0 则返回 false
115     this.isEmpty = function() {
116         return length === 0;
117     };
118 
119     // 返回链表包含元素个数。与数组的 length 属性类似
120     this.size = function() {
121         return length;
122     };
123 
124     // 由于列表项使用了 Node 类,就需要重写继承自 JavaScript 对象默认的 toString 方法,让其只输出元素的值
125     this.toString = function() {
126         var current = head,
127             string = '';
128 
129         while (current) {
130             string += current.element;
131             current = current.next;
132         }
133 
134         return string;
135     };
136 
137     this.getHead = function () {
138         return head;
139     };
140 }
LinkedList.js
 
双向链表实现:
 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     // 特定位置删除元素
57     this.removeAt = function(position) {
58         // 检查越界值
59         if (position > -1 && position < length) {
60             var current = head,
61                 previous,
62                 index = 0;
63 
64             // 移除第一项
65             if (position === 0) {
66                 head = current.next;
67 
68                 // 如果只有一项,更新tail //新增的
69                 if (length === 1) {
70                     tail = null;
71                 } else {
72                     head.prev = null;
73                 }
74             } else if (position === length-1) {
75                 current = tail;
76                 tail = current.prev;
77                 tail.next = null;
78             } else {
79                 while (index++ < position) {
80                     previous = current;
81                     current = current.next;
82                 }
83                 // 将prvious与current的下一项链接起来——跳过current
84                 previous.next = current.next;
85                 current.next.prev = previous;    // 新增的
86             }
87 
88             length--;
89 
90             return current.element;
91         } else {
92             return null;
93         }
94     };
95 }
DoublyLinkedList.js

 

参考书籍:《学习JavaScript数据结构与算法》

 

posted on 2016-03-26 10:04  Ruth92  阅读(1293)  评论(0编辑  收藏  举报

导航