源码地址:https://github.com/yhtx1997/S...javascript
另外,今天2019年2月18日上午发现 2048-vue 版,代码版本不对,且最新版本遗失,无奈只得从新修复了下
2048-vue地址: https://github.com/yhtx1997/S...html
链表存储有序的元素集合,但不一样于数组,链表中的元素在内存中并非连续放置的。每一个
元素由一个存储元素自己的节点和一个指向下一个元素的引用(也称指针或连接)组成。
相对于传统的数组,链表的一个好处在于,添加或移除元素的时候不须要移动其余元素。然
而,链表须要使用指针,所以实现链表时须要额外注意。数组的另外一个细节是能够直接访问任何
位置的任何元素,而要想访问链表中间的一个元素,须要从起点(表头)开始迭代列表直到找到
所需的元素。
以下图:
注:其中 00 06 10 12 18 为假定在内存中的地址vue
我将已经作好的链表存入数据,而后在控制台打印出来是这样的:java
它看起来就像是这样的,一层套一层node
其实应该是下面这样,相似于栓狗的铁链git
// 链表元素 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);
插入元素图解:github
如今有狗链两节,我要在中间加一节数组
先把两节分开,函数
而后把前边的尾部与要加的头部相连,而后把要加的尾部与后边的头部相连 this
0 连 xx , xx 连 1
咱们已经知道链表的每一个元素由一个存储元素自己的节点和一个指向下一个元素的引用(也称指针或连接)组成,双向链表除了这个基本特性,每一个元素还包含一个指向前一个元素的引用,如图所示:
循环链表就是链表的最后一个指向下一个元素的引用指向了第一个元素,使其成为循环链表
双向循环链表就是双向链表的第一个元素指向前一个的引用指向了最后一个元素,而最后一个元素指向下一个元素的引用指向了第一个元素,如图所示: