- 对链表进行插入排序
从前向后插入排序
维护头节点到当前节点的前一个节点为有序链表,然后把当前节点与从头节点到当前节点的前一个节点的所有节点进行比较,知道第一个大于当前节点的位置,则为当前节点的插入位置。
为了方便在头节点前插入,需要增加一个指向头节点的哑节点
class Solution {
public:
ListNode* insertionSortList(ListNode* head) {
if(head==nullptr)
return head;
ListNode *dummy = new ListNode(0);
dummy->next = head;
ListNode *tail = head;
ListNode *cur = head->next;
while(cur!=nullptr)
{
if(tail->val <= cur->val)
{
tail = tail->next;
}
else{
ListNode * pre = dummy;
while(pre->next->val <= cur->val)
pre = pre->next;
tail->next = cur->next;
cur->next = pre->next;
pre->next = cur;
}
cur = tail->next;
}
return dummy->next;
}
};
- 排序链表
进阶要求里要求时间复杂度为O(nlogn),主要有快排、归并排序、堆排序
归并排序比较适合链表
找到链表的中点,分别对链表左右两边进行排序,然后递归,将链表的左半边,右半边分别看作一个需要排序的链表,找中点,直到拆成分散的点,然后两两合并。递归这里就是起一个保存所有点的位置的作用。
找中点可以使用快慢指针
在这里插入代码片
class Solution {
public:
ListNode* sortList(ListNode* head) {
return sort1(head, nullptr);
}
ListNode* sort1(ListNode* head, ListNode* tail) {
if(head == nullptr)
return head;
if(head->next == tail)
{
head->next = nullptr;
return head;
}
ListNode* slow = head;
ListNode* fast = head;
while(fast!=tail)
{
slow = slow->next;
fast = fast->next;
if(fast!=tail)
{
fast = fast->next;
}
}
ListNode* mid = slow;
return merge(sort1(head,mid),sort1(mid,tail));
}
ListNode* merge(ListNode* head1, ListNode* head2)
{
ListNode* dummy = new ListNode(0);
ListNode* temp = dummy;
ListNode* temp1 = head1;
ListNode* temp2 = head2;
while(temp1!=nullptr&&temp2!=nullptr)
{
if(temp1->val<=temp2->val)
{
temp->next = temp1;
temp1 = temp1->next;
}
else {
temp->next = temp2;
temp2 = temp2->next;
}
temp=temp->next;
}
if(temp1!=nullptr)
temp->next=temp1;
else temp->next=temp2;
return dummy->next;
}
};