链表数据结构
- 要存储多个元素,可能常用的是数组。但是数组有一个缺点:在数组的起点和中间位置插入或移除项的成本很高,因为需要移动其它元素。链表相对于数组的好处就是添加或者删除元素不需要移动其他元素,但是要想访问链表中的元素,需要从链表的表头开始迭代列表直到找到所需元素。
- 链表存储有序集合的元素,但不同与数组,链表中的元素在内存中并不是连续放置的。每个元素由一个存储元素本身的节点和链接下一个元素的指针组成。
链式结构
创建链表
创建LinkedList,并且链表包含以下方法。
- append(element):向链表尾部添加元素
- insert(position, element):向链表指定位置添加元素
- remove(element):删除指定元素
- removeAt(position):删除指定位置的元素
- indexOf(element):返回元素在链表的引索
- isEmpty():链表是否为空
- size():链表包含的元素个数
- toString():输出元素的值
function LinkedList() {
let length = 0, // 链表的长度
head = null; // 链表的头指针
// 辅助类
let Node = function(element) {
this.element = element;
this.next = null;
}
// 向链表尾部添加指定元素
this.append = function(element) {
let node = new Node(element),
current = '';
if (head === null) {
// 链表为空
head = node;
} else {
// 链表不为空,迭代到链表最后一项,最后一项的指针等于node
current = head;
while (current.next) {
current = current.next;
}
current.next = node;
}
length++;
};
// 从链表移除指定位置的元素
this.removeAt = function(position) {
// 检查是否越界
if (position > -1 && position < length) {
let current = head,
previous = '',
index = 0;
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;
}
};
// 在任意位置插入元素
this.insert = function(position, element) {
// 检查是否越界
if (position > -1 && position < length) {
let node = new Node(element),
current = head,
previous = '',
index = 0;
if (position === 0) {
// 在第一个位置添加
head = node;
node.next = current;
} else {
while (index++ < position) {
previous = current;
current = current.next;
}
previous.next = node;
node.next = current;
}
length++;
return true;
} else {
return false;
}
};
// 返回指定项的索引
this.indexOf = function(element) {
let current = head,
index = 0;
while (current) {
if (element === current.element) {
return index;
} else {
index++;
current = current.next;
}
}
};
// 删除指定元素
this.remove = function(element) {
let index = this.indexOf(element);
return this.removeAt(index, element);
};
// 链表是否为空
this.isEmpty = function() {
return length === 0;
};
// 链表长度
this.size = function() {
return length;
};
// 把链表转换为一个字符串
this.toString = function() {
let current = head,
string = '';
while(current) {
string += current.element + (current.next ? 'n' : '');
current = current.next;
}
return string;
};
}
复制代码
// 向链表添加一项
// 链表删除一项链表相对传统数组优点是:添加删除元素不会移动其它元素。
链表相对传统数组缺点是:访问链表中间的元素,需要从头迭代,直到找到所需元素。
下一篇文章:双向链表、循环链表