LinkList

链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。

单链表

链表结构

class Node:
    def __init__(self, val):
        self.val = val
        self.next = None
class LinkList:
    def __init__(self):
        self.head = None

    def pushFront(self, ele):
        # 头插入
        node = Node(ele)
        node.next = self.head
        self.head = node

    def popFront(self):
        # 头删除
        if self.head is None:
            return
        self.head = self.head.next
        
    def show(self):
        cur = self.head
        while cur:
            print(cur.val)
            cur = cur.next

链表遍历

链表插入时间复杂度是O(1),但是查找却是O(N)

链表反转

    def reverse(self):
        if self.head is None:
            return
        cur = self.head
        pre = None
        while cur:
            pre, cur.next, cur = cur, pre, cur.next

        self.head = pre

递归写法

class Solution:
    def reverse(self, root: Node) -> Node:
        def recursion(prev: Node, cur: Node):
            if not cur:
                return prev
            nextNode = cur.next
            cur.next = prev
            prev = cur
            return recursion(prev, nextNode)

        prev = None
        cur = root

        return recursion(prev, cur)

链表合并

两个链表合并

def merge(linkA, linkB: Node) -> Node:
    if linkA is None:
        return linkB
    if linkB is None:
        return linkA
    link = None
    if linkA.val < linkB.val:
        link = linkA
        link.next = mergeLink(linkA.next, linkB)
    else:
        link = linkB
        link.next = mergeLink(linkA, linkB.next)
    return link

链表排序

这里列举一种归并排序

def merge_sort(head: Node) -> Node:
    if head is None or head.next is None:
        return head
    slow = head
    fast = head
    while fast.next and fast.next.next:
        fast = fast.next.next
        slow = slow.next

    left = head
    right = slow.next
    slow.next = None
    l = merge_sort(left)
    r = merge_sort(right)
    return merge(l, r)

双链表

双链表比起单链表多了个prev指向前一个节点

class Node:
    def __init__(self, val):
        self.val = val
        self.next = None
        self.prev = None

算法

链表有环

判断单链表是否有环

class Solution:
    def find_circle(self, head: Node):
        # 返回链表有环的点
        slow = head
        fast = head

        while fast and fast.next:
            fast = fast.next.next
            slow = slow.next
            if slow == fast:
                break
        if fast.next is None:
            # 无环
            return None
        cur = head
        while slow:
            if cur == slow:
                break
            cur = cur.next
            slow = slow.next

        return cur

LRU

用hash表和链表可以实现一个简单的LRU

class LRU:
    def __init__(self, capacity=10):
        '''index存储key对应的Node的Pre信息;head存储实际的链表'''
        self.index = {}
        # 初始化head节点
        self.head = Node(-1, -1)
        self.tail = self.head
        self.capacity = capacity

    def put(self, key, val):
        if self.get(key) != -1:
            self.index[key].next.val = val
            return
        node = Node(key, val)
        self.index[node.key] = self.tail
        self.moveToTail(node)
        if self.size() > self.capacity:
            self.evict()

    def get(self, key):
        if key not in self.index:
            return -1

        pre = self.index[key]
        cur = pre.next
        if cur != self.tail:
            pre.next = cur.next
            self.index[cur.next.key] = pre
            self.index[cur.key] = self.tail
            self.moveToTail(cur)
        return cur.val

    def moveToTail(self, node: Node):
        node.next = None
        self.tail.next = node
        self.tail = self.tail.next

    def evict(self):
        head = self.head
        # head头节点是Node(-1, -1)
        del self.index[head.next.key]
        self.index[head.next.next.key] = self.head
        self.head.next = self.head.next.next

    def size(self):
        return len(self.index)