本篇主要有三部份
- 什么是链表
- 链表的完成
- 链表的变种
源码地点:https://github.com/yhtx1997/S…
别的,本日2019年2月18日上午发明 2048-vue 版,代码版本不对,且最新版本丢失,无法只得从新修复了下
2048-vue地点: https://github.com/yhtx1997/S…
什么是链表
链表存储有序的元素鸠合,但不同于数组,链表中的元素在内存中并非一连安排的。每一个
元素由一个存储元素自身的节点和一个指向下一个元素的援用(也称指针或链接)构成。
相对于传统的数组,链表的一个优点在于,增加或移除元素的时刻不须要挪动其他元素。然
而,链表须要运用指针,因而完成链表时须要分外注重。数组的另一个细节是能够直接接见任何
位置的任何元素,而要想接见链表中心的一个元素,须要从出发点(表头)最先迭代列表直到找到
所需的元素。
如下图:
注:个中 00 06 10 12 18 为假定在内存中的地点
它看起来就像是如许的,一层套一层
实在应该是下面如许,类似于栓狗的铁链
链表的完成
链表功用
- 增加元素
- 猎取指定位置元素
- 在指定位置插进去元素
- 移除指定位置的元素
- 返回指定元素的位置
- 移除指定元素
- 是不是为空
- 长度
- 猎取表头
- 清空链表
- 转换为字符串输出
// 链表元素
class Node {
constructor(element) {
this.element = element; // 元素
this.next = undefined; // 指向下一个元素
}
}
class LinkedList {
// 组织函数声明一些全局变量
constructor(){
this.count = 0; // 长度
this.head = undefined; // 第一个元素
}
// 增加元素
push(element) {
}
// 猎取指定位置元素
getElementAt(index) {
}
// 在指定位置插进去元素
insert(element, index) {
}
// 移除指定位置的元素
removeAt(index) {
}
// 返回指定元素的位置
indexOf(element) {
}
// 移除指定元素
remove(element) {
}
// 是不是为空
isEmpty() {
}
// 长度
size() {
}
// 猎取表头
getHead() {
}
// 清空链表
clear() {
}
// 转换为字符串输出
toString() {
}
}
代码完成
class LinkedList {
// 组织函数声明一些全局变量
constructor(){
this.count = 0; // 长度
this.head = undefined; // 第一个元素
}
// 增加元素
push(element) {
const node = new Node(element);
if (this.head === undefined) {
this.head = node;
} else {
let current = this.head;
while (current.next !== undefined) {
current = current.next;
}
current.next = node;
}
this.count++;
}
// 猎取指定位置元素
getElementAt(index) {
// 推断不是空链表
if (this.isEmpty() || index > this.count || index < 0) {
// 非空才继承处置惩罚
// 推断不大于最大长度,不小于最小长度(0)
return undefined;
}
// 轮回找到元素
let current = this.head;
for (let i = 0; i < index; i++){
current = current.next;
}
return current;// 返回找到的元素
}
// 在指定位置插进去元素
insert(element, index) {
// 建立一个元素
let current = new Node(element);
// 起首肯定是不是是在首位置插进去
if (index === 0){
current.next = this.head;
this.head = current;
} else {
// 找到指定位置前一个元素
let previous = this.getElementAt(index - 1);
// 将前一个元素的 next 赋值给插进去元素的 next
current.next = previous.next;
// 将插进去元素的 node 赋值给前一个元素的 next
previous.next = current;
}
this.count++;
}
// 移除指定位置的元素
removeAt(index) {
let current = this.head;
if (index === 0){
this.head = current.next;
} else {
// 找到这个元素和这个元素之前的元素
let previous = this.getElementAt(index - 1);
current = previous.next;
// 将这个元素的 next 赋值给这个元素之前元素的 next
previous.next = current.next;
}
this.count--;
// 返回要移除的元素
return current.element;
}
// 返回指定元素的位置
indexOf(element) {
// 从头最先找
let current = this.head;
// 不凌驾最大长度
for (let i = 0; i < this.size() && current != null; i++){
if (current.element === element){ // 找到相称的就返回下标
return i;
}
current = current.next;
}
return -1;
}
// 移除指定元素
remove(element) {
// 猎取指定元素位置
let index = this.indexOf(element);
// 移除指定位置元素
return this.removeAt(index);
}
// 是不是为空
isEmpty() {
return this.size() === 0;
}
// 长度
size() {
return this.count;
}
// 猎取表头
getHead() {
return this.head;
}
// 清空链表
clear() {
this.head = undefined;
this.count = 0;
}
// 转换为字符串输出
toString() {
if (this.head == null) {
return '';
}
let objString = `${this.head.element}`;
let current = this.head.next;
for (let i = 1; i < this.size() && current != null; i++) {
objString = `${objString},${current.element}`;
current = current.next;
}
return objString;
}
}
let a = new LinkedList();
a.push('a');
a.push('b');
a.push('c');
a.push('d');
a.push('e');
a.push('f');
a.push('h');
a.push('i');
a.push('j');
a.push('k');
a.push('l');
a.push('m');
a.push('n');
a.push('o');
a.push('p');
a.push('q');
a.remove('a');
a.insert('a',1);
console.log(a);
插进去元素图解:
如今有狗链两节,我要在中心加一节
先把两节离开,
然后把前边的尾部与要加的头部相连,然后把要加的尾部与后边的头部相连
0 连 xx , xx 连 1
链表的变种
双向链表
我们已晓得链表的每一个元素由一个存储元素自身的节点和一个指向下一个元素的援用(也称指针或链接)构成,双向链表除了这个基础特征,每一个元素还包括一个指向前一个元素的援用,如图所示:
轮回链表
轮回链表就是链表的末了一个指向下一个元素的援用指向了第一个元素,使其成为轮回链表
双向轮回链表
双向轮回链表就是双向链表的第一个元素指向前一个的援用指向了末了一个元素,而末了一个元素指向下一个元素的援用指向了第一个元素,如图所示: