为链表排序量身定做的算法--归并排序
Posted C_YCBX Py_YYDS
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了为链表排序量身定做的算法--归并排序相关的知识,希望对你有一定的参考价值。
为什么说为链表排序量身定做?
很简单,如果归并排序用在数组中,是需要额外的数组作为辅助,而如果是链表,这个操作就很简单了,每次去结点直接拿下来即可,没必要畏畏缩缩,所以空间上不存在额外的使用。
看看效率:
如何实现?
归并排序三步走:
- 自顶向下分割链表,直到单个有序。(merge函数实现)
- 合并两个有序链表(mergeTwoLists函数实现)
- 根据递归特性LIFO,将分割后的单个有序结点利用mergeTwoLists排序,自底向上返回得到最终的结果。
对链表来说,难就难在分割,我们利用快慢指针寻找中点来分割。
具体代码:
class Solution {
public:
ListNode* sortList(ListNode* head) {
//剔除不需排序的特殊情况
if(!head||!head->next)
return head;
//注意是左闭右开区间[head,nullptr)
return merge(head,nullptr);
}
private:
ListNode* merge(ListNode* head,ListNode* tail){
//由于是左闭右开,所以当左端点的下一个元素等于右端点,则当前区间只含有一个结点
if (head->next == tail) {
head->next = nullptr;
return head;
}
//用快慢指针得到中间节点(fast走两步,slow走一步,当fast走到尾部则slow在中间)
ListNode* fast = head;
ListNode* slow = head;
while(fast!=tail&&fast->next!=tail){
fast = fast->next->next;
slow = slow->next;
}
//不断的分治,由于递归LIFO特性,会分解到单个结点才罢休,此时单个是有序的故可以mergeTwoLists排
//分治区间为[head,slow)U[slow,tail)
return mergeTwoLists(merge(head,slow),merge(slow,tail));
}
//合并两个有序链表的函数
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
ListNode* head;
if(!l1)return l2;
if(!l2)return l1;
if(l1->val<l2->val){
l1->next = mergeTwoLists(l1->next,l2);
head = l1;
}else{
l2->next = mergeTwoLists(l1,l2->next);
head = l2;
}
return head;
}
};
以上是关于为链表排序量身定做的算法--归并排序的主要内容,如果未能解决你的问题,请参考以下文章