链表分割【C】

给定链表头指针pHead和值x,代码将所有小于x的节点移到前面,保持原有顺序,返回新链表头指针。实现中创建了两个临时链表,分别存储小于x和大于等于x的节点,最后连接这两个链表。

描述

现有一链表的头指针 ListNode* pHead,给一定值x,编写一段代码将所有小于x的结点排在其余结点之前,且不能改变原来的数据顺序,返回重新排列后的链表的头指针。

解题思路:

<x尾插到第一个链表

>=x尾插到第二个链表

两个链表链接起来 

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) : val(x), next(NULL) {}
};*/
class Partition {
public:
    ListNode* partition(ListNode* pHead, int x) {
        // write code here
        struct ListNode *lessHead,*greaterHead,*greaterTail,*lessTail;
        lessHead=lessTail=(struct ListNode *)malloc(sizeof(struct ListNode));
        greaterTail=greaterHead=(struct ListNode *)malloc(sizeof(struct ListNode));
        lessTail->next=greaterTail->next=NULL;
        struct ListNode* cur = pHead;
        while(cur)
        {
            if(cur->val<x)
            {
                lessTail->next = cur;
                lessTail = lessTail->next;
            }
            else {
            greaterTail->next = cur;
            greaterTail=greaterTail->next;
            }
            cur=cur->next;
        }
        lessTail->next = greaterHead->next;
        greaterTail->next = NULL;
        pHead=lessHead->next;
        free(lessHead);
        free(greaterHead);
        return pHead;
    }
};

### 链表分割的实现方法 链表分割是一种常见的数据结构操作,通常用于将一个单链表按照某个条件(如节点值是否小于某个数)分成两个子链表。这种方法在排序算法、分区问题等场景中非常有用。 #### 方法一:使用两个辅助链表进行分割 一种直观的方法是创建两个新的链表头节点,分别保存小于 `x` 的节点和大于或等于 `x` 的节点。遍历原始链表时,根据节点值与 `x` 的比较结果,将节点依次连接到对应的链表中。最后将这两个链表合并[^3]。 ##### 代码示例(C++) ```cpp struct ListNode { int val; ListNode *next; ListNode(int x) : val(x), next(NULL) {} }; class Solution { public: ListNode* partition(ListNode* head, int x) { ListNode *p = new ListNode(0); // 小于x的节点链表头 ListNode *q = new ListNode(0); // 大于或等于x的节点链表头 ListNode *pHead = p; // 记录小于x的链表头 ListNode *qHead = q; // 记录大于或等于x的链表头 while (head != NULL) { if (head->val < x) { p->next = head; p = p->next; } else { q->next = head; q = q->next; } head = head->next; } q->next = NULL; // 结束大于或等于x的链表 p->next = qHead->next; // 连接两个链表 return pHead->next; // 返回新链表头 } }; ``` #### 方法二:原地调整指针 另一种方法是在原链表上直接调整指针,将符合条件的节点插入到指定位置。这种方法可以避免额外的空间开销,但逻辑上可能更复杂一些。具体实现需要维护多个指针,以便在遍历时动态调整节点的位置。 #### 方法三:Java 实现版本 在 Java 中,也可以采用类似的思路来实现链表分割。通过定义两个起始节点 `beforeStart` 和 `afterStart` 来分别记录小于 `x` 和大于或等于 `x` 的链表部分。遍历时逐个处理节点,并将其连接到相应的链表末尾,最后将两个链表拼接起来[^5]。 ##### 代码示例(Java) ```java public class ListNode { int val; ListNode next; ListNode(int val) { this.val = val; } } public class Partition { public ListNode partition(ListNode pHead, int x) { ListNode beforeStart = null; ListNode afterStart = null; ListNode beforeEnd = null; ListNode afterEnd = null; while (pHead != null) { ListNode pHeadNext = pHead.next; pHead.next = null; if (pHead.val < x) { if (beforeStart == null) { beforeStart = pHead; beforeEnd = beforeStart; } else { beforeEnd.next = pHead; beforeEnd = pHead; } } else { if (afterStart == null) { afterStart = pHead; afterEnd = afterStart; } else { afterEnd.next = pHead; afterEnd = pHead; } } pHead = pHeadNext; } if (beforeStart == null) { return afterStart; } else { beforeEnd.next = afterStart; return beforeStart; } } } ``` #### 奇偶链表分割 对于特定需求,例如将链表按奇偶索引分割成两个链表,可以通过遍历来判断当前节点的位置是否为奇数或偶数,然后分别连接到不同的链表中。这种方式常用于链表重组问题[^4]。 ##### 代码示例(C) ```c void Decollate(LinkList L, LinkList L1) { LNode *p = L->next; LNode *q = L1; LNode *m = L; int i = 1; while (p) { if (i % 2 != 0) { q->next = p; q = p; } else { m->next = p; m = p; } p = p->next; i++; } q->next = L->next; // 奇数链表结尾指向第一个节点 m->next = NULL; // 偶数链表结尾置空 } ``` #### 总结 链表分割的核心思想是根据特定条件将原始链表拆分为两个或多个子链表,并重新连接它们。上述几种方法各有优劣,可以根据实际需求选择合适的方式实现。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值