# javaScript的数据结构与算法（二）——链表

## 1、链表

### 1.1、单向链表

``````function LinkedList() {
var Node = function(element){
this.element = element;
this.next = null;
};
var length = 0;//链表长度
this.append = function(element){
var node = new Node(element),
current;
} else { //列表不为空
while(current.next){ //找到列表的最后一项
current = current.next;
}
//建立链接
current.next = node;
}
length++; //更新列表长度
};
this.insert = function(position, element){
//检查越界值
if (position >= 0 && position <= length){
var node = new Node(element),
previous,
index = 0;
if (position === 0){ //在第一个位置添加
node.next = current;
} 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){
previous,
index = 0; //用来迭代列表，直到到达目标位置
if (position === 0){ //移除第一项
} else { //移除中间或者尾部最后一项
while (index++ < position){
previous = current;
current = 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){
index = 0;
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(){
string = '';
while (current) {
string += current.element;//拼接
current = current.next;
}
return string;
};
this.print = function(){
console.log(this.toString());
};
}
``````

### 1.2、双向链表

``````function DoublyLinkedList() {
var Node = function(element){
this.element = element;
this.next = null;
this.prev = null; //新添加的
};
var length = 0;
var tail = null; //新添加的
this.append = function(element){
var node = new Node(element),
current;
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),
previous,
index = 0;
if (position === 0){ //在第一个位置
tail = node;
} else {      //列表不为空
node.next = current;
current.prev = 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; //把node节点连接进去前一个节点和后一个节点

current.prev = node; //断掉之前previous和current的连接
node.prev = previous; //prev同样需要连接
}
length++;
return true;
} else {
return false;
}
};
this.removeAt = function(position){
if (position > -1 && position < length){
previous,
index = 0;
if (position === 0){ //移除第一项
if (length === 1){ // 列表只有一项
tail = null;
} else {
}
} else if (position === length-1){ 移除最后一项
current = tail; // {4}
tail = current.prev;
tail.next = null;
} else {
while (index++ < position){
previous = current;
current = current.next;
}
previous.next = current.next; // 链接前一项和后一项，跳过当前项
current.next.prev = previous; //修复prev
}
length--;
return current.element;
} else {
return null;
}
};
this.remove = function(element){
var index = this.indexOf(element);
return this.removeAt(index);
};
this.indexOf = function(element){
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(){
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.getTail = function(){
return tail;
}
}
``````

### 1.3、循环链表

``````function CircularLinkedList() {
var Node = function(element){
this.element = element;
this.next = null;
};
var length = 0;
this.append = function(element){
var node = new Node(element),
current;
} else {
current = current.next;
}
current.next = node; //建立连接
}
length++;
};
this.insert = function(position, element){
if (position >= 0 && position <= length){
var node = new Node(element),
previous,
index = 0;
if (position === 0){ //在第一项
node.next = current;
current = current.next;
}
} else {
while (index++ < position){
previous = current;
current = current.next;
}
node.next = current;
previous.next = node;
if (node.next === null){ //在最后一个元素更新
}
}
length++;
return true;
} else {
return false;
}
};
this.removeAt = function(position){
if (position > -1 && position < length){
previous,
index = 0;
if (position === 0){
current = current.next;
}
} else {
while (index++ < position){
previous = current;
current = 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){
index = -1;
if (element == current.element){ //检查第一项
return 0;
}
index++;
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(){
s = current.element;
current = current.next;
s += ', ' + current.element;
}
return s.toString();
};
this.print = function(){
console.log(this.toString());
};
}
``````

• 序言：七十年代末，一起剥皮案震惊了整个滨河市，随后出现的几起案子，更是在滨河造成了极大的恐慌，老刑警刘岩，带你破解...
沈念sama阅读 117,643评论 1 238
• 序言：滨河连续发生了三起死亡事件，死亡现场离奇诡异，居然都是意外死亡，警方通过查阅死者的电脑和手机，发现死者居然都...
沈念sama阅读 51,126评论 1 200
• 文/潘晓璐 我一进店门，熙熙楼的掌柜王于贵愁眉苦脸地迎上来，“玉大人，你说我怎么就摊上这事。” “怎么了？”我有些...
开封第一讲书人阅读 72,773评论 0 167
• 文/不坏的土叔 我叫张陵，是天一观的道长。 经常有香客问我，道长，这世上最难降的妖魔是什么？ 我笑而不...
开封第一讲书人阅读 35,753评论 0 127
• 正文 为了忘掉前任，我火速办了婚礼，结果婚礼上，老公的妹妹穿的比我还像新娘。我一直安慰自己，他们只是感情好，可当我...
茶点故事阅读 42,544评论 1 204
• 文/花漫 我一把揭开白布。 她就那样静静地躺着，像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上，一...
开封第一讲书人阅读 35,328评论 1 124
• 那天，我揣着相机与录音，去河边找鬼。 笑死，一个胖子当着我的面吹牛，可吹牛的内容都是我干的。 我是一名探鬼主播，决...
沈念sama阅读 27,288评论 2 206
• 文/苍兰香墨 我猛地睁开眼，长吁一口气：“原来是场噩梦啊……” “哼！你这毒妇竟也来了？” 一声冷哼从身侧响起，我...
开封第一讲书人阅读 26,427评论 0 119
• 想象着我的养父在大火中拼命挣扎，窒息，最后皮肤化为焦炭。我心中就已经是抑制不住地欢快，这就叫做以其人之道，还治其人...
爱写小说的胖达阅读 25,389评论 5 170
• 序言：老挝万荣一对情侣失踪，失踪者是张志新（化名）和其女友刘颖，没想到半个月后，有当地人在树林里发现了一具尸体，经...
沈念sama阅读 29,446评论 0 177
• 正文 独居荒郊野岭守林人离奇死亡，尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
茶点故事阅读 26,700评论 1 167
• 正文 我和宋清朗相恋三年，在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
茶点故事阅读 27,938评论 1 176
• 白月光回国，霸总把我这个替身辞退。还一脸阴沉的警告我。[不要出现在思思面前， 不然我有一百种方法让你生不如死。]我...
爱写小说的胖达阅读 22,285评论 0 24
• 序言：一个原本活蹦乱跳的男人离奇死亡，死状恐怖，灵堂内的尸体忽然破棺而出，到底是诈尸还是另有隐情，我是刑警宁泽，带...
沈念sama阅读 24,871评论 2 163
• 正文 年R本政府宣布，位于F岛的核电站，受9级特大地震影响，放射性物质发生泄漏。R本人自食恶果不足惜，却给世界环境...
茶点故事阅读 28,716评论 3 172
• 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹，春花似锦、人声如沸。这庄子的主人今日做“春日...
开封第一讲书人阅读 23,692评论 0 4
• 文/苍兰香墨 我抬头看了看天上的太阳。三九已至，却和暖如春，着一层夹袄步出监牢的瞬间，已是汗流浃背。 一阵脚步声响...
开封第一讲书人阅读 23,785评论 0 113
• 我被黑心中介骗来泰国打工， 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留，地道东北人。 一个月前我还...
沈念sama阅读 29,903评论 2 187
• 正文 我出身青楼，却偏偏与公主长得像，于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子，可洞房花烛夜当晚...
茶点故事阅读 30,330评论 2 188