链表的实现:链表储存有序的元素集合,但是和数组不同的是,链表中的元素在内存中不是连续放置的,每个元素由一个储存元素本身的节点和一个指向下一个元素的引用(指针、链接)
向空的链表中添加一个元素:
向不为空的链表尾部添加元素:
从链表中移除第一个元素:
从链表中移除最后一个元素:
从链表中间移除一个元素:
在链表的开头添加一个元素:
在链表的最后添加一个元素:
在链表的中间添加一个元素:
function LinkedList() {
let Node = function (element) {
this.element = element;
this.next = null;
};
let length = 0;
let head = null;
this.append = function(element){
//向列表尾部添加一个新的元素
let node = new Node(element);
let current;
if(head === null){
head = node;
}else{
current = head;
while(current.next){
current = current.next;
}
//找到最后一项,将其next 赋为node,建立连接
current.next = node;
}
length++;//更新列表的长度
};
this.insert = function (position, element) {
//向列表特定的位置插入一个新的项
//检查是否越界
if(position >= 0 && position < length){
let 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;
}
};
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.next = current.next;
}
length--;
return current.element;
}else{
return null;
}
};
this.indexOf = function (element) {
//返回元素在列表中的索引,如果列表中没有该元素就返回-1
let current = head,
index = -1;
while(current){
if(element === current.element){
return index;
}
index++;
current = current.next;
}
return -1;
};
this.isEmpty = function () {
//列表中不包含任何元素就返回true,否则返回false
return length === 0;
};
this.size = function () {
//返回链表的元素个数
return length;
};
this.toString = function () {
//重写js对象默认的 toString 方法
let current = head,
string = '';
while(current){
string += current.element;
}
return string;
};
this.remove = function (element) {
//从列表中移除一项
let index = this.indexOf(element);
return this.removeAt(index);
};
this.getHead = function () {
return head;
};
}
双向链表:连接是双向的——一个链向下一个元素,一个链向前一个元素
在开头插入一个元素:
在链表最后添加一个元素:
在链表中间插入一个元素:
双向链表移除第一个元素:
最后一个位置移除元素:
从双向链表中间位置移除一个元素:
具体实现:
}function DoublyLinkedList() {
var Node = function(element){
this.element = element;
this.next = null;
this.prev = null;
};
var length = 0;
var head = null;
var tail = null;
this.append = function(element){
var node = new Node(element),
current;
if (head === null){ //链表的第一项
head = node;
tail = node;
} else {
/
tail.next = node;
node.prev = tail;
tail = node;
}
length++; //更新链表长度
};
this.insert = function(position, element){
//检查边界值
if (position >= 0 && 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){
//检查是否超出边界
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's next 连接起来——跳过current
previous.next = current.next;
current.next.prev = previous;
}
length--;
return current.element;
} else {
return null;
}
};
this.remove = function(element){
var index = this.indexOf(element);
return this.removeAt(index);
};
this.indexOf = function(element){
var current = head,
index = -1;
//检查第一个位置
if (element == current.element){
return 0;
}
index++;
//检查中间位置元素
while(current.next){
if (element == current.element){
return index;
}
current = current.next;
index++;
}
//检查链表尾部元素
if (element == current.element){
return index;
}
return -1;
};
this.isEmpty = function() {
return length === 0;
};
this. size = function() {
return length;
};
this.toString = function(){
var current = head,
s = current ? current.element : '';
while(current && current.next){
current = current.next;
s += ', ' + current.element;
}
return s;
};
this.inverseToString = function() {
var current = tail,
s = current ? current.element : '';
while(current && current.prev){
current = current.prev;
s += ', ' + current.element;
}
return s;
};
this.print = function(){
console.log(this.toString());
};
this.printInverse = function(){
console.log(this.inverseToString());
};
this.getHead = function(){
return head;
};
this.getTail = function(){
return tail;
}
循环链表:
单向循环链表:
最后一个元素的指针指向第一个元素,而不是引用null
双向链表:指向head 元素的 tail.prev ,指向tail 元素的 head.prev
function CircularLinkedList() {
var Node = function(element){
this.element = element;
this.next = null;
};
var length = 0;
var head = null;
this.append = function(element){
var node = new Node(element),
current;
if (head === null){ //链表为空,添加第一个元素
head = node;
} else {
current = head;
//迭代链表直到找到最后一个元素
while(current.next !== head){ //最后一个元素设置为head
current = current.next;
}
//最后一个元素链接到node
current.next = node;
}
//设置node.next 链接到head 构成一个循环链表
node.next = head;
length++; //更新链表长度
};
this.insert = function(position, element){
//检查是否超出边界
if (position >= 0 && position <= length){
var node = new Node(element),
current = head,
previous,
index = 0;
if (position === 0){ //在循环链表开头添加
node.next = current;
//设置最后一个元素
while(current.next !== head){ //最后一个元素设置为head
current = current.next;
}
head = node;
current.next = head;
} else {
while (index++ < position){
previous = current;
current = current.next;
}
node.next = current;
previous.next = node;
if (node.next === null){
node.next = head;
}
}
length++; //更新链表长度
return true;
} else {
return false;
}
};
this.removeAt = function(position){
//检查是否超出边界
if (position > -1 && position < length){
var current = head,
previous,
index = 0;
//移除开头元素
if (position === 0){
while(current.next !== head){ //先设置最后一个元素的指向
current = current.next;
}
head = head.next;
current.next = head;
} else { //末尾元素不需要更新
while (index++ < position){
previous = current;
current = current.next;
}
//将previous.next 和 current.next链接起来
previous.next = current.next;
}
length--;
return current.element;
} else {
return null;
}
};
this.remove = function(element){
var index = this.indexOf(element);
return this.removeAt(index);
};
this.indexOf = function(element){
var current = head,
index = -1;
//检查开头元素
if (element == current.element){
return 0;
}
index++;
//检查链表中间元素
while(current.next !== head){
if (element == current.element){
return index;
}
current = current.next;
index++;
}
//检查链表最后元素
if (element == current.element){
return index;
}
return -1;
};
this.isEmpty = function() {
return length === 0;
};
this.size = function() {
return length;
};
this.getHead = function(){
return head;
};
this.toString = function(){
var current = head,
s = current.element;
while(current.next !== head){
current = current.next;
s += ', ' + current.element;
}
return s.toString();
};
this.print = function(){
console.log(this.toString());
};
}
(这个链表真的是晦涩难懂,绕来绕去的,但是跟结合图片来理解还是可以接受的,这恐怕是有史以来我最长的记录笔记的博文)