//链表
/*
* LinkedList 数据结构还需要一个Node辅助类,Node类表示要加入列表的项,它包含一个element属性,
* 即要添加到列表的值,以及一个next属性,即指向列表中下一个节点项的指针
* append(element): 向列表尾部添加一个新的项
* insert(position, element):在列表的特定位置插入一个新的项
* removeAt(position):从列表的特定位置移除一项
* remove(element):从列表中删除一项
* indexOf(element):返回元素在列表中的索引,如果列表中没有该元素则返回-1
* isEmpty():如果列表中不包含任何元素,返回true,否则返回false
* size():返回列表包含的元素个数
* toString():由于列表项用了Node类,就需要重写javascript对象默认的toString方法,让其只输出元素的值
*/
function LinkedList() {
var Node = function(element) {
this.element = element;
this.next = null; // 指向列表下一项的指针
}
var length = 0;//LinkedList类也有存储列表项的数量length属性(内部/私有变量)
var head = null;// 存储第一个节点的引用,
this.append = function(element) {
// 向列表中添加项的时候,要考虑俩种情况:1、列表为空,此时添加的是列表中的第一个元素,2、列表不为空,向其追加元素
var node = new Node(element), current;
if(head === null) { // 列表中的一个节点
head = node; // 列表最后一个节点的下一个元素始终是null
}else {
current = head;
//循环列表,知道找到最后一项
while(current.next) {
current = current.next;
}
//找到最后一项,将其next赋值为node,建立链接
current.next = node;
}
length++;
};
this.insert = function(position, element) {
if(position > -1 && position <= length) {
var node = new Node(element);
current = head;
previous, index = 0;
if(position === 0) {
node.next = current;
head = node;
} else {
while(index++ < position) { //循环列表找到目标位置
previous = current;
current = current.next;
}
node.next = current;
previous.next = node;
}
length++;
return true;
}else {
return false;
}
};
// 移除元素有俩种情景:1、移除第一个元素;2、移除第一个元素以外的任一元素;
this.removeAt = function(position) {
// 检查越界值
if(position > -1 && position < length) {
var current = head, previous, index = 0;
// current是要移除元素的引用,previous是对要移除元素的前一个元素的引用,移除current,需要做的是将previous.next 与 current.next链接起来
// 移除第一项
if(position === 0) {
head = current.next;
}else {
while(index++ < position) {
previous = current;
current = current.next;
}
// 将previous与current的下一项链接起来:跳过current,从而移除它
previous.next = current.next;
}
length--;
return current.element;
}else {
return null; // 不是有效位置,则返回null
}
};
this.remove = function(element) {
};
this.indexOf = function (element) {
var current = head, index = -1;
while(current) {
if(element === current.element) {
return index;
}
index++;
current = current.next;
}
return -1;
};
this.isEmpty = function() {
return length === 0;
};
this.size = function() {
return length;
};
this.toString = function() {
var current = head, string = '';
while(current) {
string = current.element;
current = current.next;
}
return string;
};
this.print = function() {};
this.getHead = function() {
return head;
}
}
var linkedList = new LinkedList();
linkedList.append(15);
linkedList.append(10);
// 双向链表
function DoublyLinkedList() {
var Node = function(element) {
this.element = element;
this.next = null;
this.prev = null;
}
var length = 0;
var head = null;
var tail = null;
// 向双向链表中插入一个新项跟(单向)链非常类似,区别在于,链表只要控制一个next指针,而双向链表则要同时控制next和prev
this.insert = function(position, element) {
if(position > -1 && position <= length) {
var node = new Node(element),
current = head, previous, index = 0;
if(position === 0) { // 在第一个位置
if(!head) { //新增的
head = node;
tail = node;
}else {
node.next = current;
current.prev = node;
head = node;
}
}else if(position === length) {
current = tail;
current.next = node;
node.prev = current;
tail = node;
}else {
while(index++ < position) {
previous = current;
current = current.next;
}
node.next = current;
previous.next = node;
current.prev = node;
node.prev = previous;
}
length++;
return true;
} else {
return false;
}
}
this.removeAt = function(position, element) {
if(position > -1 && position < length) {
var current = head, previous, index = 0;
if(position === 0) {
head = current.next;
if(length === 1) {
tail = null;
}else {
head.prev = null;
}
}else if(position === length - 1) {
current = tail;
tail = current.prev;
tail.next = null;
}else {
while(index++ < position) {
previous = current;
current = current.next;
}
// 将previous与current的下一项链接起来--跳过current
previous.next = current.next;
current.next.prev = previous;
}
length--;
return current.element;
}else {
return null;
}
}
}
// 循环链表: 最后一个元素指向下一个元素的指针next不是null,而是指向第一个元素head