1-单项链表
function LinkedList() { let Node = function(element) { // 辅助类,表示要添加到链表中的项 this.element = element; this.next = null; //next属性是只想链表的下一个节点的指针 }; let length = 0, head = null; // 头指针 this.append = function(element) {}; // 向链表尾部添加一个新的项 this.insert = function(element, position) {}; // 向指定位置插入一个新的项 this.removeAt = function(position) {}; // 移除链表中的指定项 this.remove = function(element) {}; // 移除值为element的项 this.indexOf = function(element) {}; // 返回元素在链表中的索引,如果没有则返回-1 this.isEmpty = function() {}; // 判断链表中是否为空 this.size = function() {}; // 链表的长度 this.clear = function() {}; // 清空链表 this.print = function() {}; //输出链表的值 }
append实现:向链表尾部添加一个新的项
this.append = function(element) { //向链表尾部添加一个新的项 let node = new Node(element), current; if (head === null) { // 链表中的第一个节点 head = node; } else { current = head; while (current.next) { // 循环链表,直到找到最后一项 current = current.next; } current.next = node; // 找到最后一项,将next赋值为node,建立连接 } length += 1; //更新链表长度 };
print实现:输出链表的值
this.print = function() { let current = head; for (let i = 0; i < length; i++) { console.log(`第${i+1}个值:${current.element}`); current = current.next; } };
insert实现:向指定位置插入一个新的项
向指定位置插入一个新的项,步骤如下:
- 先进行position的越界判断!!
- case1: 当position=0的时候,那就是直接将当前head指向的节点变成新建node的next指向,head指向新建的node上
- case2: 除case1外的情况,先遍历到如下图所示的情况,我们设置两个指针,每次遍历都是current将值赋给previous,然后current向后推进,直到current指向position的位置,previous指向position的前一个
- 然后将新建的node,插入其中,然后改变其中的指针指向,具体看代码
- 最后将length加一
this.insert = function(element, position) { // 向指定位置插入一个新的项 if (position >= 0 && position <= length) { // 检查越界值 let node = new Node(element), current = head, // 设置两指针 previous; if (position === 0) { // 在第一个位置添加 node.next = head; head = node; }else { for (let i = 0; i < position; i++) { // 使得current定在要插入的位置,previous定在要插入位置的前一个位置 previous = current; current = current.next; } // 将新项node插入进去 node.next = current; previous.next = node; } }else { return 0; } length += 1; };
对于函数参数含有position这类的位置参数,一定要注意越界判断
removeAt实现:移除链表中的指定位置项
removeAt的思想和前面的insert方法很相似,唯一的不同就是移除指定项时,改变指针指向的代码不同previous.next = current.next;
,
- 具体思想如图:将current指向的项(其实也就是position指向的项)移除,那就将图中红色叉的指针指向取消,然后用新的代替
- 然后将lenght减一
- 只有
previous.next = current.next;
和insert方法不同,其他思想和做法都一样
this.removeaAt = function(position) { // 移除链表中的指定项 if (position >= 0 && position <= length) { let current = head, previous; if (position === 0) { head = head.next; }else { for (let i = 0; i < position; i++) { //此处循环到current指向要移除的位置,同insert方法 previous = current; current = current.next; } // 通过将previous的next变化到current.next,将指定项移除 previous.next = current.next; } }else { return 0; } length -= 1; };
indexOf实现:返回元素在链表中的索引,如果没有则返回-1
this.indexOf = function(element) { // 返回元素在链表中的索引,如果没有则返回-1 let current = head; // for (let i = 0; i < length; i++) { if (current.element === element) { return i; } current = current.next; } return -1; };
remove实现:移除值为element的项
this.remove = function(element) { // 移除值为element的项 // remove方法可以直接通过复用 this.indexOf(element) 和 this.removeAt(position) 方法实现 let index = this.indexOf(element); return this.removeaAt(index); };
isEmpty、size、clear实现
this.isEmpty = function() { // 判断链表中是否为空 return length === 0; }; this.size = function() { // 链表的长度 return length; }; this.clear = function() { // 清空链表 let current = head; for (let i = 0; i < length; i++) { this.removeAt(i); } length = 0; head = null; };
测试函数
(function LinkedListTest() { let linked = new LinkedList(); linked.append(2); linked.append(3); linked.append(4); linked.print(); // 第1个值:2 第2个值:3 第3个值:4 linked.insert(5, 1); // 位置从0开始 linked.print(); // 第1个值:2 第2个值:5 第3个值:3 第4个值:4 linked.removeAt(1); // 相当于将上面插入的5再删除 linked.print(); // 第1个值:2 第2个值:3 第3个值:4 console.log(linked.indexOf(3)); // 1 console.log(linked.indexOf(10)); // -1 console.log(linked.size()); // 3 console.log(linked.isEmpty()); // false linked.clear(); console.log(linked.isEmpty()); // true })();