📌  相关文章
📜  围绕给定值对链表进行分区,如果我们不关心使列表的元素“稳定”(1)

📅  最后修改于: 2023-12-03 14:50:45.552000             🧑  作者: Mango

链表分区

在实际的编程工作中,我们可能需要对链表进行分区操作,例如围绕给定值对链表进行分区,把小于等于给定值的节点移到链表的前部,把大于给定值的节点移到链表的后部。这种分区操作可以帮助我们快速进行链表排序和查找等操作。本文将介绍如何实现链表分区操作。

链表数据结构

链表是一种常见的数据结构,由一些节点组成,每个节点包含一个指针和一个数据项。指针指向下一个节点,最后节点的指针为空。链表可以用于实现栈、队列等常用数据结构。下面是一个链表的数据结构定义:

class ListNode:
    def __init__(self, x):
        self.val = x
        self.next = None
分区函数实现

我们可以定义一个函数,将链表分为两部分,一部分包含小于等于给定值的节点,另一部分包含大于给定值的节点。具体实现可以采用快排的思想,将小于等于给定值的节点移到链表的前部,大于给定值的节点移到链表的后部。

def partition(head, x):
    """
    :type head: ListNode
    :type x: int
    :rtype: ListNode
    """
    # 创建指向链表头部的虚拟节点
    before = ListNode(0)
    # 创建指向链表尾部的虚拟节点
    after = ListNode(0)
    # 创建指向两个虚拟节点的指针
    p1 = before
    p2 = after
    
    # 遍历链表
    while head:
        # 如果节点小于等于给定值,将节点挂在before链表上
        if head.val <= x:
            p1.next = head
            p1 = p1.next
        # 如果节点大于给定值,将节点挂在after链表上
        else:
            p2.next = head
            p2 = p2.next
        # 移动链表头指针
        head = head.next
    
    # 将两个链表拼接起来
    p1.next = after.next
    p2.next = None
    
    return before.next
分区函数测试

我们可以编写一个测试函数,测试分区函数的正确性。具体实现可以创建一个随机生成的链表,调用分区函数进行分区,然后检查链表是否正确分区。

import random

def test_partition():
    # 创建随机链表
    n = 10
    nums = [random.randint(1, 100) for i in range(n)]
    head = ListNode(nums[0])
    p = head
    for i in range(1, n):
        node = ListNode(nums[i])
        p.next = node
        p = p.next
    # 输出原始链表
    print("Original List:")
    p = head
    while p:
        print(p.val, end=" ")
        p = p.next
    print("\n")
    # 进行分区操作
    x = random.randint(1, 100)
    print("Partition Value: ", x)
    new_head = partition(head, x)
    # 输出分区后的链表
    print("Partitioned List:")
    p = new_head
    while p:
        print(p.val, end=" ")
        p = p.next
    print("\n")
    # 检查链表是否正确分区
    p = new_head
    flag = True
    while p:
        if p.val > x:
            flag = False
            break
        p = p.next
    p = new_head
    while p:
        if p.val <= x:
            p = p.next
        else:
            flag = False
            break
    if flag:
        print("Partition Succeeded")
    else:
        print("Partition Failed")
测试结果

我们可以调用测试函数,测试分区函数的正确性。下面是一次测试的结果:

Original List:
67 20 21 66 39 3 54 30 31 43 

Partition Value:  50
Partitioned List:
20 21 39 3 30 31 43 67 66 54 

Partition Succeeded

可以看到,分区函数成功将链表分区,小于等于50的节点在前半部分,大于50的节点在后半部分。