链表

120 阅读2分钟

什么是链表?

由多个元素组成的列表 元素存储不连续,用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));