比较基础,不用多说了。LeetCode上链表的设计
function Linkdedlist () {
function Node (val) {
this.val = val;
this.next = null;
}
this.head = null;
this.length = 0;
Linkdedlist.prototype.addAtHead = function (val) {
var newNode = new Node(val);
if (this.length === 0) this.head = newNode;
else {
newNode.next = this.head;
this.head = newNode;
}
this.length++;
}
// 下标从0开始
Linkdedlist.prototype.get = function (index) {
if (this.length === 0) return -1;// 链表为空,index无论是多少都无效
if (index < 0 || index > this.length - 1) return -1;// 链表不为空,不在链表长度范围的值都无效
let i = 0;//记录下标的值
let p = this.head;//移动指针
while (i < this.length && i < index) {
p = p.next;
i++;
}
return p.val;
}
Linkdedlist.prototype.addAtTail = function (val) {
let newNode = new Node(val);
if (this.length === 0) {
this.head = newNode;//链表为空,直接设置为头
} else {
let p = this.head;
while (p.next != null) {
p = p.next;//移动到末尾
}
p.next = newNode;//插入到末尾
}
this.length++;
}
Linkdedlist.prototype.tostring = function () {
let result = '';
let p = this.head;
while (p) {
result += p.val + " ";
p = p.next;
}
return result;
}
// addAtIndex(index, val) :在链表中的第 index 个节点之前添加值为 val 的节点。如果 index 等于链表的长度,则该节点将附加到链表的末尾。如果 index 大于链表长度,则不会插入节点。如果index小于0,则在头部插入节点。
Linkdedlist.prototype.addAtIndex = function (index, val) {
let newNode = new Node(val);
if (index <= 0) { //小于等于,插入到head前
newNode.next = this.head;
this.head = newNode;
this.length++;
} else if (index == this.length) {//等于链表长度,插入到最后
let p = this.head;
while (p.next) {
p = p.next;
}
p.next = newNode;
this.length++;
} else if (index > this.length) {//超过链表长度,什么都不做
return;
} else {//插入到链表内部
let p = this.head;
let q = p;
let i = 0;
while (i < index) {//newNode节点,就是要插入道p,q中间的节点
// console.log(i);
p = q;
q = q.next;
i++;
}
newNode.next = q;
p.next = newNode;
this.length++;
}
}
// deleteAtIndex(index) :如果索引 index 有效,则删除链表中的第 index 个节点。
Linkdedlist.prototype.deleteAtIndex = function (index) {
if (index < 0 || index > this.length - 1) return;
if (this.length == 0) return;
let i = 0;
let p = this.head;
let q = p;
/**
* 第一种情况index=0 this.head = this.head.next;
* 第二种情况index = this.length -1 只要设置 p.next = null;(此时q为要删除的元素,即最后一个,所以q.next=null) 即p.next = q.next;
* 第三种情况index在首末位之间 p.next = q.next;
*/
if (index === 0) this.head = this.head.next;
else {
while (i < index) {
p = q;
q = q.next;
i++;
}
p.next = q.next;
}
this.length--;
}
// 下面是新加的方法,没有用到上面中
Linkdedlist.prototype.size = function () {
return this.length;
}
Linkdedlist.isEmpty = function () {
return this.length === 0 ? true : false;
}
// 链表的反转
/**
* 将链表 分为两部分 , 一部分是反转的 , 部分是还未反转的 , 初始化的时候,p和q是在未进行反转的头部,而this.head这一个节点是反转的头部
* p是要插入到this。head之前的节点 , q是在未进行
*/
Linkdedlist.prototype.reversalList = function () {
if (this.length === 0) return false;
if (this.length === 1) return;
let p = this.head.next, q = p;
this.head.next = null;
while (p) {
q = p.next;
// p.next = null;//先将q指到下一个节点,然后再将p从该链表中断开 , 这步断开p.next时为了更好理解
p.next = this.head;//将断开的p追加到头结点
this.head = p;
p = q;//将p追加到头结点之后,要将p指针再次指向q,进行下一轮
}
}
// 判断链表中是否有环(快慢指针)
Linkdedlist.prototype.hasCircle = function () {
if (this.length <= 1) return false;
let fast = this.head, slow = this.head;
while (fast.next && fast.next.next) {
fast = fast.next.next;
slow = slow.next;
if (fast === slow) {
return true;
}
}
return false;
}
}
let list = new Linkdedlist();
list.addAtHead(1);
list.addAtTail(3);
list.addAtIndex(1, 2);
// console.log(list.tostring());
console.log(list.get(1));
list.deleteAtIndex(1);
// console.log(list.tostring());
console.log(list.get(1));
// list.addAtTail('zxx');
// list.addAtHead('mmm');
// list.addAtTail('nnn');
// list.addAtTail('ooo');
// console.log(list.tostring());
// console.log(list.get(1));
// console.log(list.get(2));
// console.log(list.get(4));
// console.log(list.get(5));
// console.log(list.get(-1));
// list.deleteAtIndex(0);
// console.log("delete:", list.tostring());
// list.deleteAtIndex(3);
// console.log("delete:", list.tostring());
// list.deleteAtIndex(1);
// console.log("delete:", list.tostring());