今天的工作中需要用到JavaScript的链表,于是我上网找了一些资料。发现了这篇博客:
http://www.cnblogs.com/snandy/archive/2011/10/14/2212491.html
里面有一个JavaScript脚本LinkedList-0.1.js,代码的地址在:
http://files.cnblogs.com/files/snandy/LinkedList-0.1.js
原作者Snandy已经对代码包括的函数做了说明,并给出了一个调用例子。
基本上这些内容已经满足我的需要,不过因为原代码的get函数返回的是数据而不是节点,不适于做链表的遍历,因此我在原代码的基础上做了一些改进。新增了三个函数getNode、getFirstNode、getLastNode,分别作为原get、getFirst、getLast的扩展。
改动后的代码LinkedList.js如下(改动的地方用注释标出)
/**
* 原作者:snandy 2011
* 修改人:Tsybius2014 2015年11月23日
*/
LinkedList = function(){
function Node(data, next) {
this.data = data || null;
this.next = next || null;
}
Node.prototype = {
getValue: function() {
return this.data;
},
setValue: function(obj) {
this.data = obj;
},
getNext: function() {
return this.next;
},
setNext: function(node) {
this.next = node;
}
};
Node.prototype.constructor = Node;
function nodeByIndex(index, head) {
var node = head;
var i = 0;
if(index===0) {
return node;
}
while(node.next) {
if(i===index) {
return node;
}
node = node.next && node.next;
i++;
}
return node;
}
function nodeByData(data, list) {
var prev = null,
node = list.head;
while(node.next) {
if(node.data == data) {
if(node==list.head) {
return {
prev: null,
curr: node
};
}
else {
return {
prev: prev,
curr: node
};
}
}
prev = node;
node = node.next;
}
if(node.data == data) {
if(list.size() === 1) {
return {
prev: null,
curr: node
};
}
else {
return {
prev: prev,
curr: node
};
}
}
return null;
}
function LinkedList() {
this.head = null;
this.tail = null;
this.length = 0;
}
LinkedList.prototype = {
add: function(index, obj) {
if(obj === undefined || obj === null || typeof index != 'number') {
throw new Error('add failed, invalid param');
}
if(index < 0) {
index = this.length + index;
}
if(index<0 || index>this.length) {
throw new Error('add failed, invalid index');
}
var newNode = new Node(obj);
if(index==0) {
if(this.head) {
newNode.setNext(this.head);
this.head = newNode;
}
else {
this.head = this.tail = newNode;
}
}
else {
var node = nodeByIndex(index-1, this.head),
next = node.next;
node.setNext(newNode);
newNode.setNext(next);
}
this.length++;
},
//获取指定索引的节点(新加的代码)
getNode: function(index) {
if(typeof index !== 'number') {
throw new Error('get failed, invalid param');
}
if(index < 0) {
index = this.length + index;
}
if(this.isEmpty() || index<0 || index>=this.length) {
throw new Error('Index: ' + index + ', Size: ' + this.length);
}
var node = nodeByIndex(index, this.head);
return node;
},
get: function(index) {
return this.getNode(index).data;
},
//获取首个节点(新加的代码)
getFirstNode: function() {
return this.getNode(0);
},
getFirst: function() {
return this.get(0);
},
//获取最后一个节点(新加的代码)
getLastNode: function() {
return this.getNode(this.length-1);
},
getLast: function() {
return this.get(this.length-1);
},
set: function(index, obj) {
if(index < 0) {
index = this.length + index;
}
if(this.isEmpty() || index<0 || index>=this.length) {
throw new Error('Index: ' + index + ', Size: ' + this.length);
}
var node = nodeByIndex(index, this.head);
node.data = obj;
},
size: function() {
return this.length;
},
clear: function() {
this.head.next = null;
this.head = null;
},
remove: function(obj) {
var nodes = nodeByData(obj, this);
if(nodes === null) {
throw new Error('remove failed, the node does not exist');
}
var curr = nodes.curr,
prev = nodes.prev;
if(prev === null) {
this.head = curr.next;
curr.next = null;
curr = null;
}
else {
prev.setNext(curr.next);
curr.next = null;
curr = null;
}
this.length--;
},
isEmpty: function() {
return this.head === null;
},
addLast: function(obj) {
this.add(this.length, obj);
},
addFirst: function(obj) {
this.add(0, obj);
},
contains: function(obj) {
var node = this.head;
if(this.isEmpty()) {
return false;
}
while(node.next) {
if(node.data == obj) {
return true;
}
node = node.next;
}
if(node.data == obj) {
return true;
}
return false;
},
toString: function() {
var str = '',
node = this.head;
if(this.isEmpty()) {
return '[]';
}
str = '[' + node.data;
while(node.next) {
node = node.next;
str += ',' + node.data;
}
str += ']';
return str;
}
};
LinkedList.prototype.constructor = LinkedList;
return LinkedList;
}();
我另建立了一个html文件,取名为test.html,用于测试这段JavaScript,代码如下:
<!DOCTYPE HTML>
<HTML>
<HEAD>
<TITLE>单向链表</TITLE>
<script src="LinkedList.js"></script>
<script>
document.write("创建链表<br/>");
var list = new LinkedList();
document.write("添加元素 one/two/three/four <br/>");
list.addLast('元素【one】');
list.addLast('元素【two】');
list.addLast('元素【three】');
list.addLast('元素【four】');
document.write("链表内元素个数:" + list.size() + "<br/>");
document.write("输出链表内全部元素:");
document.write(list);
document.write("<br/>");
document.write("遍历链表内全部元素1:");
for (var i = 0; i < list.size(); i++)
{
document.write(list.get(i));
if (i < list.size() - 1) {
document.write(",");
} else {
document.write(".");
}
}
document.write("<br/>");
document.write("遍历链表内全部元素2:");
var node = list.getFirstNode();
while (node != null)
{
document.write(node.getValue());
node = node.getNext();
if (node != null) {
document.write(",");
} else {
document.write(".");
}
}
document.write("<br/>");
document.write("测试完毕");
</script>
</HEAD>
<BODY>
</BODY>
</HTML>
用Chrome浏览器测试后,效果如下:
END