拿捏链表(六)—— 链表分割
现有一链表的头指针 ListNode* pHead,给一定值x,编写一段代码将所有小于x的结点排在其余结点之前,且不能改变原来的数据顺序,返回重新排列后的链表的头指针。题目来源
这道题涉及的知识点
1.链表的尾插
2.链表带环问题
分析一下题意:
我们现在有一个链表,给定了一个值x,链表中小于x的数放到前面,大于x的放到后面,
然后返回一个调整后的链表
例如:2,4,9,3,2,1,6
返回:2,4,3,2,1,9,6
因为题目要求相对顺序不变
所以不能如下这样
2,3,4,1,2,6,9
如果题目没有要求相对顺序不变,我们可以通过尾插和头插的方式,把小于x的值进行头插,把大于x的值进行尾插。
既然题目有要求我们只能换种方式
现在我们创建两个新链表,一个存放小于x的数,一个存放大于x的数。
然后最后把两个链表链接到一起
上述的图知识大概的分析整个过程,接下来我们具体分析
因为要取数据的结点,所以我们要定义一个指针cur来遍历pHead链表,
创建两个链表,为了方便尾插,我们用有哨岗的方式定义两个链表
分别为lessHead,greaterHead,
然后再定义两指针,方便尾插,不需要每次尾插时都要遍历链表找到尾结点,
没插入一个数我们就用尾指针记录
通过上述的分析,我们来看看然后实现代码,下面的代码有问题的!!
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};
class Partition {
public:
ListNode* partition(ListNode* pHead, int x) {
ListNode* greaterHead, *greaterTail, *lessHead, *lessTail;
//申请一个头结点,后面链接大于x的结点
greaterHead = greaterTail = (ListNode*)malloc(sizeof(struct ListNode));
//申请一个头结点,后面链接小于x的结点
lessHead = lessTail = (ListNode*)malloc(sizeof(struct ListNode));
greaterTail->next = NULL;//尾指针的指针域置空
lessTail->next = NULL;//尾指针的指针域置空
ListNode* cur = pHead;//接收传入的链表,准备遍历
while (cur)
{
if (cur->val < x)
{
//结点值小于x,链接到less链表后面
lessTail->next = cur;
lessTail = lessTail->next;
}
else
{
//结点值大于x,链接到greater链表后面
greaterTail->next = cur;
greaterTail = greaterTail->next;
}
cur = cur->next;//指针后移,遍历后面的结点
}
//将less链表和greater链表链接起来
lessTail->next = greaterHead->next;//greater链表的第一个结点链接到less链表的尾上
ListNode* head = lessHead->next;//接收链接后链表的第一个结点地址
free(greaterHead);//释放greater链表的头结点
free(lessHead);//释放less链表的头结点
return head;//返回新链表
}
};
内存超限,原因在于出现死循环了,
我们继续画图分析
我们发现,两链表链接在一起时,2指向5,然后7又指向了2,2有指向5,7又指向2……
链表出现了死循环,我们都知道链表的特性就是尾结点后为空,作为结束条件
所以我们应该让greaterHead链表的最后一个结点指向后面为空,这样就可以解决了
好了现在我们只需要在原有上进行修改
在两链表进行合并之前,cur遍历完以后,添加尾结点指向下一个结点为空即可
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};
class Partition {
public:
ListNode* partition(ListNode* pHead, int x) {
ListNode* greaterHead, *greaterTail, *lessHead, *lessTail;
//申请一个头结点,后面链接大于x的结点
greaterHead = greaterTail = (ListNode*)malloc(sizeof(struct ListNode));
//申请一个头结点,后面链接小于x的结点
lessHead = lessTail = (ListNode*)malloc(sizeof(struct ListNode));
greaterTail->next = NULL;//尾指针的指针域置空
lessTail->next = NULL;//尾指针的指针域置空
ListNode* cur = pHead;//接收传入的链表,准备遍历
while (cur)
{
if (cur->val < x)
{
//结点值小于x,链接到less链表后面
lessTail->next = cur;
lessTail = lessTail->next;
}
else
{
//结点值大于x,链接到greater链表后面
greaterTail->next = cur;
greaterTail = greaterTail->next;
}
cur = cur->next;//指针后移,遍历后面的结点
}
//将less链表和greater链表链接起来
lessTail->next = greaterHead->next;//greater链表的第一个结点链接到less链表的尾上
greaterTail->next = NULL;//将greater链表最后一个结点的指针域置空
ListNode* head = lessHead->next;//接收链接后链表的第一个结点地址
free(greaterHead);//释放greater链表的头结点
free(lessHead);//释放less链表的头结点
return head;//返回新链表
}
};