分割链表
- 1.题目来源
- 2.题目描述
- 3.解题思路
- 4.代码展示
所属专栏:玩转数据结构题型
博主首页:初阳785
代码托管:chuyang785
感谢大家的支持,您的点赞和关注是对我最大的支持!!!
博主也会更加的努力,创作出更优质的博文!!
关注我,关注我,关注我,重要的事情说三遍!!!!!!!!
1.题目来源
分割链表
2.题目描述
给你一个链表的头节点 head 和一个特定值 x ,请你对链表进行分隔,使得所有 小于 x 的节点都出现在 大于或等于 x 的节点之前。
你不需要 保留 每个分区中各节点的初始相对位置。
3.解题思路
本题的意思就是说把下小于x的数据放在左边,大于等于x的数据放在右边,在改变顺序的同时不改变原来的的循序。
我们的思路是创建两个链表,一个链表LessHead放小于下的数据,另一个链表greaterHead放大于等于x的数据,最后把两个两边合并成一个链表,然后返回新链表的首节点地址就行了。
为了方便链接,我们使用创建哨兵的方法来作为两个链表的头节点,所谓哨兵为就是它的val是无效数据,但是它的next指向下一个地址。
接着我们创建一个变量cur来遍历我们的链表,然后根据他们的大小来给他们分配到不同的链表里去。
图解:
当x=3 的时候,cur开始遍历,首先是第一个节点的数据是1它比3小我们就把他链接到我们的LessHead链表中去,同时我们用LessNext来记录链接过来的节点点的地址,在以后往后链接的时候只需要用LessHead表示就好,这样的好处是链接完后我们返回链表的头节点的地址的时候就直接返回LessHead就行了。
同样的cur遍历完第一个后只需要是cur=cur->next就可以访问第二个节点了,因为我们在链接第一个节点的时候并没有破坏我们第一个节点指向我们第二个节点的通道,我们依然可以通过第一个节点找到第二个节点,同样的我们用greaterNext来表示我们接下来的节点地址。
以此类推到我们的cur指向NULL的时候我们的循环就停止了。
接着就是将两个链表合并就行。
我们只需要将lessTail->next=greaterHead->next;就行了。
但是这里有个特别重要的事情就是我们连接完后我们的greaterNext指向那里了?它真的就指向了NULL吗?答案是否定的。
我们回到之前链接的时候:
我们看到这里我们的存放5数据的next是指向2的地址的。
所以他的图像解析就变成了这个样子,如果是这样的话,就成环了,再返回地址的时候内存就会出问题。
所以这里的解决方案就是把我们的greaterNext->next置空即:greaterNext->next=NULL。
4.代码展示
struct ListNode* partition(struct ListNode* head, int x)
{
//创建哨兵位,方便链接
struct ListNode* lessHead,*lessTail,*greaterHead,*greaterTail;
//存放小于x的数据
lessHead=lessTail=(struct ListNode*)malloc(sizeof(struct ListNode));
lessHead->next=NULL;
//存放大于等于x的数据
greaterHead=greaterTail=(struct ListNode*)malloc(sizeof(struct ListNode));
greaterHead->next=NULL;
//遍历链表指针
struct ListNode* cur=head;
while(cur)
{
//尾插
if(cur->val < x)
{
lessTail->next=cur;
lessTail=cur;
}
else
{
greaterTail->next=cur;
greaterTail=cur;
}
cur=cur->next;
}
//链接两个链表
lessTail->next=greaterHead->next;
//消除环,我们的5最后还指向我们2,这个时候就形成了一个环、
greaterTail->next=NULL;
struct ListNode* newnode=lessHead->next;
//最后释放两个创建的内存空间
free(lessHead);
free(greaterHead);
return newnode;
}