【C语言数据结构】分割链表

        . - 力扣(LeetCode)

        这里挂上题目链接

        给你一个链表的头节点 head 和一个特定值 x ,请你对链表进行分隔,使得所有 小于 x 的节点都出现在 大于或等于 x 的节点之前。

        你不需要 保留 每个分区中各节点的初始相对位置。

        比方说下面的例子,x为3

1 先来理理题目逻辑

        还是刚刚的例子

        这里x为3

        题目要求吧所有小于3的全部挪到链表的左边,大于等于3的全部挪到链表的右边,顺序无所谓

        我们就可以新建两条链,一条左链,一条右链,我们把小于3的全部放进左链里面,把所有大于等于3的全部放进右链里面

        就像这样

        接着我们连接左链末尾和右链指针就得到了题目所需要的链了

        因为我们要连接左右两条链,所以我们还需要两条链的头尾节点指针

        接着我们只需要返回左链的头节点L_list_head就可以了

2 接下来我们来实现一下

        首先我们肯定要有个指针用来遍历原链表

    //这个指针用来遍历原链表
    ListNode* pcur = head;

        同时我们也要定义左右链表的头尾指针

    //这四个指针分别是left部分和right部分的头节点和尾节点
    ListNode* L_list_head = NULL;
    ListNode* L_list_tail = NULL;
    ListNode* R_list_head = NULL;
    ListNode* R_list_tail = NULL;

        初始状态下左右链表的头尾节点指向空

        接着我们判断pcur指向的内容是否小于3

        因为左链的头尾节点都指向为空,所以我们要单独判断一下(别忘了把pcur往后挪!

if(pcur->val < x)
{
    //新建左链第一个节点
    if(L_list_head == NULL && L_list_tail == NULL)
    {
        L_list_head = pcur;
        L_list_tail = pcur;
    }
    //左链尾插
    else
    {
        L_list_tail->next = pcur;
        L_list_tail = L_list_tail->next;
    }
    pcur = pcur->next;
}

 

         接着我们再此判断pcur指向的内容是否小于3,这里显然是大于3的,因此要尾插到右链里

        此时右链也为空,所以我们依旧要判断一下(同样别忘了把pcur往后挪!

else
{
    //新建右链第一个节点
    if(R_list_head == NULL && R_list_tail == NULL)
    {
        R_list_head = pcur;
        R_list_tail = pcur;
    }
    //右链尾插
    else
    {
        R_list_tail->next = pcur;
        R_list_tail = R_list_tail->next;
    }
    pcur = pcur->next;
}

        因为要遍历原链表,所以我们就把以上代码放进循环里

        这里pcur后挪重复了,就挪到if else外面

//遍历原链表并分割为左右两个链表
while(pcur != NULL)
{
    if(pcur->val < x)
    {
        //新建左链第一个节点
        if(L_list_head == NULL && L_list_tail == NULL)
        {
            L_list_head = pcur;
            L_list_tail = pcur;
        }
        //左链尾插
        else
        {
            L_list_tail->next = pcur;
            L_list_tail = L_list_tail->next;
        }
    }
    else
    {
        //新建右链第一个节点
        if(R_list_head == NULL && R_list_tail == NULL)
        {
            R_list_head = pcur;
            R_list_tail = pcur;
        }
        //右链尾插
        else
        {
            R_list_tail->next = pcur;
            R_list_tail = R_list_tail->next;
        }
    }
    //pcur后移
    pcur = pcur->next;
}

        最后连接左右两个链表

//连接左右链表
if(L_list_tail != NULL && R_list_tail != NULL)
{
    L_list_tail->next = R_list_head;
    R_list_tail->next = NULL;    
}

        最后返回左链头节点就行

return L_list_head;

         当然还有一些特殊情况

        如果原链表就为空,没东西遍历了,就直接返回原链表就行了

//原链表为空就返回原链表,反正是NULL
if(head == NULL)
{
    return head;
}

        还有,如果左链啥也没有,那就不能返回左链头节点了,左链头节点就是空

        我们就返回右链头节点

//左链啥都没有就返回右链
if(L_list_tail == NULL)
{
    return R_list_head;
}

3 完整代码

struct ListNode {
    int val;
    struct ListNode *next;
};

//重命名
typedef struct ListNode ListNode;

struct ListNode* partition(struct ListNode* head, int x)
{
    //原链表为空就返回原链表,反正是NULL
    if(head == NULL)
    {
        return head;
    }
    //这个指针用来遍历原链表
    ListNode* pcur = head;

    //这四个指针分别是left部分和right部分的头节点和尾节点
    ListNode* L_list_head = NULL;
    ListNode* L_list_tail = NULL;
    ListNode* R_list_head = NULL;
    ListNode* R_list_tail = NULL;

    //遍历原链表并分割为左右两个链表
    while(pcur != NULL)
    {
        if(pcur->val < x)
        {
            //新建左链第一个节点
            if(L_list_head == NULL && L_list_tail == NULL)
            {
                L_list_head = pcur;
                L_list_tail = pcur;
            }
            //左链尾插
            else
            {
                L_list_tail->next = pcur;
                L_list_tail = L_list_tail->next;
            }
        }
        else
        {
            //新建右链第一个节点
            if(R_list_head == NULL && R_list_tail == NULL)
            {
                R_list_head = pcur;
                R_list_tail = pcur;
            }
            //右链尾插
            else
            {
                R_list_tail->next = pcur;
                R_list_tail = R_list_tail->next;
            }
        }
        //pcur后移
        pcur = pcur->next;
    }
    
    //连接左右链表
    if(L_list_tail != NULL && R_list_tail != NULL)
    {
        L_list_tail->next = R_list_head;
        R_list_tail->next = NULL;    
    }
    
    //左链啥都没有就返回右链
    if(L_list_tail == NULL)
    {
        return R_list_head;
    }
    
    return L_list_head;
}

求赞求赞求赞,感谢感谢感谢  >v<    

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值