Python链表排序

前置函数

class ListNode:
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next

def build_list(listInput):
    node = None
    for i in range(len(listInput)-1, -1, -1):
        node = ListNode(val=listInput[i], next=node)
    return node

def print_list(head):
    node = []
    cur = head
    while cur:
        node.append(cur.val)
        cur = cur.next
    print(node)

# 测试代码
nodes = [4, 2, 1, 3, 1, 6]
head = build_list(nodes)

ob = Solution()
res = ob.sortList(head )

冒泡排序

class Solution:
    def sortList(self, head):
        # 如何输入链表为空,或者只有一个元素就直接返回
        if not head or not head.next: return head
        # 统计链表里面元素的个数n
        cur = head
        n = 0
        while cur:
            n += 1
            cur = cur.next
        # 构造一个虚拟头结点
        headNew = ListNode(val=0, next=head)
        # 冒泡排序法实现链表的排序
        for i in range(1, n):
            print_list(headNew.next)
            pre = headNew
            cur = headNew.next
            nex = headNew.next.next
            for j in range(n-i):
                nex_nex = nex.next
                if cur.val > nex.val:
                    # 如果当前元素的值大于它的下一个元素的值
                    # 说面要进行交换
                    # 分三步:
                    # 1、下个元素指向当前元素
                    # 2、当前元素指向下下元素
                    # 3、前元素指向下个元素
                    nex.next = cur
                    cur.next = nex_nex
                    pre.next = nex
                    # 更新前元素为下个元素
                    # 当前元素不能再更新,因为前面已经更新为中间元素了
                    pre = nex
                else:
                    # 正常更新前元素和当前元素
                    pre = cur
                    cur = nex
                # 更新下个元素为下下元素
                nex = nex_nex
        return headNew

打印结果

[4, 2, 1, 3, 1, 6]
[2, 1, 3, 1, 4, 6]
[1, 2, 1, 3, 4, 6]
[1, 1, 2, 3, 4, 6]
[1, 1, 2, 3, 4, 6]

插入排序

class Solution:
    def sortList(self, head):
        if not head or not head.next: return head
        newHead = ListNode(val=0, next=head)
        # 插入排序法实现链表的排序
        # 指向链表的虚拟头结点
        # 每次从头开始比较每个元素与当前元素的大小
        # 用来确定当前元素该插入链表中的哪个位置
        pre = newHead
        # 为了指向已经排好序的链表的最后一个元素
        lastSorted = newHead.next
        # 当前元素,即未排序中的第一个元素,
        # 也是lastSorted后面的一个元素
        cur = newHead.next.next
        while cur:
            print_list(newHead.next)
            if cur.val < lastSorted.val:
                # 循环遍历,直到找到当前元素该插入的位置
                while pre.next.val < cur.val:
                    pre = pre.next
                ### 核心交换部分
                # 链表位置交换
                lastSorted.next = cur.next
                cur.next = pre.next
                pre.next = cur
                ### 交换结束
                # 更新cur和pre
                cur = lastSorted.next
                pre = newHead
            else:
                # 更新cur和lastSorted
                cur = cur.next
                lastSorted = lastSorted.next
        return newHead.next

打印结果

[4, 2, 1, 3, 1, 6]
[2, 4, 1, 3, 1, 6]
[1, 2, 4, 3, 1, 6]
[1, 2, 3, 4, 1, 6]
[1, 1, 2, 3, 4, 6]

注意:由于插入没有像冒泡排序那样每次对比都进行位置的交换,而是找到插入位置后直接将当前元素放在插入位置,虽然时间复杂度仍是O(N^2),但交换的次数明显比冒泡排序少,所以比冒泡排序还是快不少

归并排序

猜你喜欢

转载自blog.csdn.net/qq_33757398/article/details/125942718