def selection_sort_swap_value(link: Link) -> Link:
    """
    选择排序

    不交换节点,只交换值的方式
    """
    head_node = Node(0, link.head_node)
    start_node = head_node.next_node
    while start_node:
        swap_node = None
        current_node = start_node.next_node
        while current_node:
            if current_node < start_node:
                if not swap_node or swap_node > current_node:
                    swap_node = current_node

            current_node = current_node.next_node

        if swap_node:
            swap_node.element, start_node.element = start_node.element, swap_node.element

        start_node = start_node.next_node

    link.head_node = head_node.next_node
    return link
def optimize_insertion_sort(link: Link) -> Link:
    """
    优化插入排序

    测试:
        链表的长度为 1000 --- Total execution time: 235 ms
        链表的长度为 10000 --- Total execution time: 23785 ms

    leetcode:
        link: https://leetcode-cn.com/problems/insertion-sort-list/
        执行用时: 220 ms, 在所有 Python3 提交中击败了 74.71% 的用户
        内存消耗: 15.3 MB, 在所有 Python3 提交中击败了 12.50% 的用户
    """
    head_node = Node(0, link.head_node)

    current_node = link.head_node
    while current_node and current_node.next_node:
        if current_node <= current_node.next_node:
            current_node = current_node.next_node
            continue

        start_node = head_node
        while start_node.next_node < current_node.next_node:
            start_node = start_node.next_node

        temp_node = current_node.next_node
        current_node.next_node = temp_node.next_node
        temp_node.next_node = start_node.next_node
        start_node.next_node = temp_node

    link.head_node = head_node.next_node
    return link
def insertion_sort(link: Link) -> Link:
    """
    插入排序

    测试:
        链表的长度为 1000 --- Total execution time: 286 ms
        链表的长度为 10000 --- Total execution time: 30442 ms

    leetcode:
        link: https://leetcode-cn.com/problems/insertion-sort-list/
        执行用时: 2564 ms, 在所有 Python3 提交中击败了 9.48% 的用户
        内存消耗: 15.3 MB, 在所有 Python3 提交中击败了 12.50% 的用户

    问题:
        1.使用了新的空间
        2.进行了多次的比较

    优化:
        1.在不断链的情况下进行排序
        2.减少比较次数
    """

    new_head_node = None
    current_node = link.head_node

    while current_node:
        next_node = current_node.next_node
        current_node.next_node = None

        if not new_head_node:
            new_head_node = current_node
        else:
            node = new_head_node
            last_node = None
            while node:
                if node > current_node:
                    current_node.next_node = node
                    if not last_node:
                        new_head_node = current_node
                    else:
                        last_node.next_node = current_node
                    break

                elif not node.next_node:
                    node.next_node = current_node
                    break

                last_node = node
                node = node.next_node

        current_node = next_node

    link.head_node = new_head_node
    return link
def reverse_link(link: Link) -> Link:
    " 反转链表 "
    new_head_node = None
    current_node = link.head_node
    while current_node:
        next_node = current_node.next_node
        current_node.next_node = new_head_node
        new_head_node = current_node
        current_node = next_node

    link.head_node = new_head_node
    return link
def quicksort_main_swap_node(link: Link) -> Link:
    """
    快速排序(递归,交换节点)

    测试:
        链表的长度为 1000 --- Total execution time: 19 ms
        链表的长度为 10000 --- Total execution time: 239 ms
    """
    head_pre_node = Node(0, link.head_node)
    quicksort_swap_node(head_pre_node, link.head_node, None)
    link.head_node = head_pre_node.next_node
    return link
def merge_sort_main(link: Link) -> Link:
    """
    归并排序(递归)

    测试:
        链表的长度为 1000 --- Total execution time: 14 ms
        链表的长度为 10000 --- Total execution time: 175 ms

    leetcode:
        link: https://leetcode-cn.com/problems/sort-list/submissions/
        执行用时: 224 ms, 在所有 Python3 提交中击败了 67.87% 的用户
        内存消耗: 20.7 MB, 在所有 Python3 提交中击败了 28.57% 的用户
    """
    link.head_node = merge_sort(link.head_node)
    return link
def selection_sort(link: Link) -> Link:
    """
    选择排序

    说明:
        1. 交换任意两个节点,需要用定位到它们的父节点
        2. 要分相邻和不相邻两种情况处理

    测试:
        链表的长度为 1000 --- Total execution time: 656 ms
        链表的长度为 10000 --- Total execution time: 67671 ms
    """
    head_node = Node(0, link.head_node)

    start_node = head_node
    while start_node.next_node:
        parent_node = None

        current_node = start_node.next_node
        while current_node.next_node:
            if current_node.next_node < start_node.next_node:
                if not parent_node or parent_node.next_node > current_node.next_node:
                    parent_node = current_node

            current_node = current_node.next_node

        if parent_node:
            if parent_node.next_node == start_node.next_node.next_node:
                # 相邻
                swap_node = parent_node.next_node
                start_node.next_node.next_node = swap_node.next_node
                swap_node.next_node = start_node.next_node
                start_node.next_node = swap_node
            else:
                # 不相邻
                swap_node_a = start_node.next_node
                swap_node_b = parent_node.next_node

                swap_node_b.next_node, swap_node_a.next_node = swap_node_a.next_node, swap_node_b.next_node

                start_node.next_node = swap_node_b
                parent_node.next_node = swap_node_a

        start_node = start_node.next_node

    link.head_node = head_node.next_node
    return link
def merge_sort_no_recursion(link: Link) -> Link:
    """归并排序(非递归)

    说明:
        将所有节点,两两归并,再四个四个归并,以此类推

    测试:
        链表的长度为 1000 --- Total execution time: 25 ms
        链表的长度为 10000 --- Total execution time: 595 ms

    Arguments:
        link {Link} -- 链表

    Returns:
        Link -- 链表
    """
    head_node = Node(0, link.head_node)
    length = 0
    current = head_node.next_node
    while current:
        length += 1
        current = current.next_node

    end = math.sqrt(length)
    end += 1 if not end.is_integer() else 0
    for i in range(0, int(end)):
        new_head = head_node
        current = head_node.next_node
        while current:
            right = current
            left = cut_link(current, pow(2, i))
            current = cut_link(left, pow(2, i))
            new_head.next_node = merge_link(right, left)
            while new_head.next_node:
                new_head = new_head.next_node

    link.head_node = head_node.next_node
    return link