class Solution {
public:
// 1. getTail API
ListNode* getTail(ListNode *head){
while(head->next){
head = head->next;
}
return head;
}
ListNode* quickSortList(ListNode* head) {
// 2. 空节点或单节点
if(!head || !head->next) return head;
// 3. 单链表表头为helper
ListNode *lhead = new ListNode(-1), *mhead = new ListNode(-1), *rhead = new ListNode(-1);
auto left = lhead, mid = mhead, right = rhead;
// 4.遍历链表
int x = head->val;
for(auto p = head; p ; p = p->next){
if (p->val < x)
left = left->next = p; // 5. 插入元素 + 移动指针
else if (p->val == x)
mid = mid->next = p;
else
right = right->next = p;
}
// 得到三个链表,递归左边和右边链表
left->next = mid->next = right->next = nullptr; // 6.各个链表尾部置null
//7. 只需遍历左区间 与 右区间
lhead->next = quickSortList(lhead->next);
rhead->next = quickSortList(rhead->next);
//8. 链表拼接
getTail(lhead)->next = mhead->next;
getTail(mhead)->next = rhead->next;
// 9. 专门的re
auto re = lhead->next;
// 10. 内存回收
delete lhead;
delete mhead;
delete rhead;
return re;
}
};
是因为 ListNode lhead = new ListNode(-1), mhead = new ListNode(-1), *rhead = new ListNode(-1);
这个操作使得每一个头节点都是-1,
所以,拼接时以及返回时都是返回 ->next 吗?
’‘’
// 3. 单链表表头为helper
ListNode lhead = new ListNode(-1), mhead = new ListNode(-1), *rhead = new ListNode(-1);
auto left = lhead, mid = mhead, right = rhead;
’‘’
这一段代码将>x,=x,<x连成三段链表,简洁巧妙!(同时不要忘记给三段链表尾部截断)
请问为什么要做第6步呢
不做第六步,在递归结束进行合并的时候
会无法完成,因为无法搜索到传入下一个递归的尾巴位置。你可以理解为完成单次快排之后,链表各个区间就完全断开了,在递归全部完成之后,才把他们依次合并。