什么是链表?
由多个元素组成的列表 元素存储不连续,用next指针连在一起
a -(next)-> b -(next)-> c
数组 vs 链表
数组:增删非首尾元素时往往需要移动元素 链表:增删非首尾元素时更改next指针就行了
实现
function linkedList() {
this.a = null;
this.mid = null;
this.first = null
this.push = (item) => {
let obj = { val: item };
if (!this.mid) {
this.a = obj;
this.first = obj
} else {
this.mid.next = obj;
}
this.mid = obj;
};
this.midPush = function (left, right, item) {
if (!this.a) {
this.push(item);
return;
}
let i = null;
let j = null;
let p = this.a;
while (p) {
if (p.val == left) {
i = p;
}
if (p.val == right) {
j = p;
break;
}
p = p.next;
}
let obj = { val: item };
i.next = obj;
obj.next = j;
};
this.delete = function (item) {
let p = l.peek();
while (p) {
if(p.next.val == item){
break
}
p = p.next;
}
p.next = p.next.next
};
this.peek = function () {
return this.a;
};
this.getFirst = function(){
return this.first
}
}
例题
反转链表
利用栈的解法
let p = l.peek();
let arr = []
while (p) {
arr.push(p.val)
p = p.next;
}
console.log(arr);
let l1 = new linkedList
for(let i = arr.length-1;i >=0; i--){
l1.push(arr[i])
}
console.log(l1.peek());
双指针遍历
a -> b -> c -> d
temp = b
a(p1) -> null(p2)
p2 = p1 = a
p1 = temp = b
b(p1) -> a(p2)
let a = {val:'a'}
let b = {val:'b'}
let c = {val:'c'}
let d = {val:'d'}
let head = a
a.next = b
b.next = c
c.next = d
let p1 = a
let p2 = null
while (p1) {
let temp = p1.next
p1.next = p2
p2 = p1
p1 = temp
}
console.log(p2);
俩数相加
/**
* Definition for singly-linked list.
* function ListNode(val, next) {
* this.val = (val===undefined ? 0 : val)
* this.next = (next===undefined ? null : next)
* }
*/
/**
* @param {ListNode} l1
* @param {ListNode} l2
* @return {ListNode}
*/
var addTwoNumbers = function(l1, l2) {
let l3 = new ListNode(0)
//顶部元素
let p1 = l1
let p2 = l2
let p3 = l3
let carry = 0;
while(p1 || p2){//俩个链表只要有一个存在就一直循环
const v1 = p1 ? p1.val : 0
const v2 = p2 ? p2.val : 0
const val = v1 + v2 +carry
carry = Math.floor(val / 10)
p3.next = new ListNode(val % 10)
if(p1) p1 = p1.next
if(p2) p2 = p2.next
p3 = p3.next
}
if(carry){
p3.next = new ListNode(carry)
}
return l3.next
};
//就是对应的位数相加超过10进1就行
删除重复元素
//因为给的链表是有序的,所以重复元素一定相邻
/**
* Definition for singly-linked list.
* function ListNode(val, next) {
* this.val = (val===undefined ? 0 : val)
* this.next = (next===undefined ? null : next)
* }
*/
/**
* @param {ListNode} head
* @return {ListNode}
*/
var deleteDuplicates = function (head) {
let p = head
while(p && p.next){
if(p.val === p.next.val){
p.next = p.next.next
}else{
p = p.next
}
}
return head
};
环形链表
//一快一慢俩指针,交汇代表有
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} head
* @return {boolean}
*/
var hasCycle = function(head) {
let p1 = head//慢
let p2 = head//快
while(p1 && p2 && p2.next){
p1 = p1.next
p2 = p2.next.next
if(p1 === p2){
return true
}
}
return false
};
回文链表
/**
* Definition for singly-linked list.
* function ListNode(val, next) {
* this.val = (val===undefined ? 0 : val)
* this.next = (next===undefined ? null : next)
* }
*/
/**
* @param {ListNode} head
* @return {boolean}
*/
var isPalindrome = function (head) {
let len = 0
let p = head
while(p){
len++;
p = p.next
}
if(len === 1) return true
let midLen = Math.trunc(len / 2)
let p1 = head
let p2 = null
//循环一半拿到中间值
for(let i = 0;i<midLen;i++){
p1 = p1.next
}
//判断是否平分 【1,0,1】==> true
if(midLen * 2 === len){
p2 = p1.next
}else{
p2 = p1.next.next
}
//反转p1//此时p1是中间值
let p3 = head
let p4 = head.next
let tmp = null
while(p3 != p1){
p3.next = tmp
tmp = p3
p3 = p4
p4 = p4.next
}
p3.next = tmp
while(p1){
if(p1.val !== p2.val){
return false
};
p1 = p1.next
p2 = p2.next
}
return true
};
原型链
let arr = []
console.log(arr instanceof Array);
function ins(A,B){
let p = A
while(p){
if(p === B.prototype){
return true
}
p = p.__proto__
}
return false
}
console.log(ins(arr,Array));
console.log(ins(arr,Function));