LeetCode 148. 排序链表(Medium)【多种排序方法!!!】

在这里插入图片描述
在这里插入图片描述
【题目链接】

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next

class Solution:
    ### 自底向上归并排序()
    def sortList(self, head: ListNode) -> ListNode:
        if not head: return

        # 初始化:伪头节点h指向head(伪头节点用于遍历链表),链表长度length为0,归并排序的子链表长度intv为最小长度1
        h, length, intv = head, 0, 1

        # 初始化:指向头节点head的辅助节点res
        res = ListNode(0)
        res.next = head

        # 遍历一遍链表,得到链表长度
        while h: h, length = h.next, length + 1

        # 当子链表的长度小于原始链表长度时,对链表进行归并排序
        while intv < length:
            # 归并排序每轮合并过程开始时,重新初始化:用于链接两个子链表的辅助节点pre与伪头节点h
            pre, h = res, res.next

            # 当链表本轮还未局部排序完时,进行循环
            while h:
                ## 断链过程 Cut
                # 移动链表来确定第一个子链表中元素个数情况
                h1, i = h, intv
                while i > 0 and h: h, i = h.next, i - 1

                # 若第一个子链表的元素个数不足本轮的intv,则不存在第二个子链表,直接终止循环
                if i > 0: break

                # 移动链表来确定第二个子链表中元素个数情况(此时从上一步剩余的h继续判断,表示将两个子链表分开Cut)
                h2, i = h, intv
                while i > 0 and h: h, i = h.next, i - 1

                ## 合并过程 Merge
                # 合并时需要确定两个子链表的元素数量(其中第二个子链表中元素数量可能不足本轮的intv,因此需要减去上一步中剩余的i个元素)
                n1, n2 = intv, intv - i
                # 当两个子链表中均剩余元素时,可以进行大小比较
                while n1 > 0 and n2 > 0:
                    # 根据元素值大小来排序,选择正确的值来链接链表,并移动链表
                    if h1.val < h2.val: pre.next, h1, n1 = h1, h1.next, n1 - 1
                    else: pre.next, h2, n2 = h2, h2.next, n2 - 1

                    pre = pre.next # 每链接完一个元素,pre后移一位

                # 处理可能剩余的链表元素,并让pre移动到已经排序完成的元素之后
                pre.next = h1 if n1 > 0 else h2
                while n1 > 0 or n2 > 0: pre, n1, n2 = pre.next, n1 - 1, n2 - 1

                # 将剩余未排序的元素链接到pre之后
                pre.next = h

            # 本轮归并完成,下一轮的intv翻倍
            intv *= 2

        return res.next # 最后返回链表头

其他排序方法

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值