链表相关算法

235 阅读2分钟

一周过的真快本周主要学习了几个链表相关的算法载这里与大家分享一下

  1. 链表

    • 什么是链表?

    我这里简单理解为一种数据存储结构通过指针进行逻辑连接每一个单元由值和下一个单元的地址构成。更详细的链表概念请点击这里

  2. 数组转链表

    数据结构转换工具方法 // 每个单元节点 class Node { data; next = null; constructor(data){ this.data = data } }

        class linkedList{
           head = null;
           length = 0;
           add(val){
               let node = new Node(val);
               if(this.length == 0) {
                   // 如果链表是空的那么默认第一节点是头节点;
                   this.head = node;
               }else {
                   // 获取头节点;
                   let cur = this.head;
                   
                   // 判断当前节点是否有下一个节点
                   while(cur.next != null){
                       cur = cur.next;
                   }
                   
                   cur.next = node;
                   
               }
               length++;
           }
        }
        
        // 最终转化为此结构
        [1,2,3,4]
        head:{
            data:1,
            next:{
                    data:2,
                    next:{
                        data:3,
                        next:{
                            data:4,
                            next:null
                        }
                    }
                  }
        }
    
  3. 链表转数组

    数据结构转换工具方法 function linkedToArray(head) { let arr = []; while(head){ arr.push(head); head = head.next; } return arr; } // 有上文数组转链表的结构转为数组结构

两个链表相连接

> 简单理解把两个链表拼接起来
```
function mergeTwoList(l1,l2){
    // 预设一个头节点
    let fakehead = new ListNode(0);
    let current = fakehead;

    // 两个链表都不为空
    while(l1 && l2){
        
        // 链表1中的值如果小于链表2的值那么把 l1 给新链表的next 否则会把另外一个的链表的值给新链表的next
        if(l1.val < l2.val){
            current.next = l1;
            l1 = l1.next;
        } else {
            current.next = l2;
            l2 = l2.next;
        }

        // 指针后移
        current = current.next;
    }

    // 指针后移
    if(l1){
        current.next = l1;
    }
    // 指针后移
    if(l2){
        current.next = l2;
    }

    return fakehead.next;
}
```

两个链表相交

> 简单理解找出两个链表重叠起来地部分
链表1扫完接着扫链表2 
链表2扫完接着扫链表1
如果有重合的部分说明有重叠如果没有说明没有重叠

链表相交.gif ``` function inserSect(headA,headB){ let l1 = headA; let l2 = headB; while(l1 != l2) {

            if(l1.next === null){
                l1 = headB;
            }else{
                l1 = l1.next;
            }
            
            if(l2.enxt === null){
               l2 = headA;
            }else {
               l2 = l2.next;
            }
        }
        
        return l1;
        
    }
```

链表反转

> 简单理解就是把链表的指针的指向倒过来

链表.gif

```
    function reverseLinked(head){
        let pre = null; // 当前节点的前一个位置,第一个节点之前没有所以为null
        let cur = head; // 当前节点同步当前节点位置 
        
        while(cur){
            // 断开 当前节点指针,指向前一个节点位置,移动位置到一个节点
            const next = cur.next;
            cur.next = pre;
            pre = cur;
            cur = next;
        }
        
        return pre;
    }
```

链表旋转

环型实现还好,新的头部节点和新的尾部节点的确认自己容易出错

function rotateRight(head, k) {

    if(k === 0 || !head || !head.next) {
        return head;
    }

    
    
    // 实现环形链表
    let n = 1;
    let cur = head;

    // 确定新的尾部节点的位置
    let add = n - k % n;
    if( add == 0 ) {
        return head;
    }

    while(cur.next) {
        cur = cur.next; 
        n++;
    }


    cur.next = head;

    

    while(add) {
        cur = cur.next; 
        add--;
    }

    const ret = cur.next;

    cur.next = null;

    return ret;


    
}