链表排序的最佳方法是 归并排序,其基本思想是将链表分割成小部分,然后对每个小部分进行排序,最终将整个链表排成一个有序链表。以下是归并排序在链表排序中的应用:
找到中间节点:
使用快慢指针法找到链表的中间节点。
分割链表:
将链表从中间节点断开,形成两个子链表。
递归排序:
对两个子链表递归地应用上述步骤,直到每个子链表只包含一个节点。
合并有序链表:
将两个有序子链表合并成一个有序链表。
```cpp
class Solution {
public:
ListNode* sortList(ListNode* head) {
if (!head || !head->next) return head;
// 使用快慢指针找到中间节点
ListNode* slow = head;
ListNode* fast = head->next;
while (fast && fast->next) {
slow = slow->next;
fast = fast->next->next;
}
// 分割链表
ListNode* mid = slow->next;
slow->next = nullptr;
// 递归排序左右两部分
ListNode* left = sortList(head);
ListNode* right = sortList(mid);
// 合并有序链表
return merge(left, right);
}
ListNode* merge(ListNode* l1, ListNode* l2) {
ListNode dummy(0);
ListNode* cur = &dummy;
while (l1 && l2) {
if (l1->val < l2->val) {
cur->next = l1;
l1 = l1->next;
} else {
cur->next = l2;
l2 = l2->next;
}
cur = cur->next;
}
if (l1) cur->next = l1;
if (l2) cur->next = l2;
return dummy.next;
}
};
```
其他排序方法
除了归并排序,链表还可以使用其他排序方法,例如:
插入排序:
从第一个元素开始,依次将每个元素插入到已排序部分的适当位置。插入排序的时间复杂度为O(N^2),空间复杂度为O(1)。
```cpp
class Solution {
public:
ListNode* insertionSortList(ListNode* head) {
if (!head || !head->next) return head;
ListNode dummy(0);
ListNode* cur = head;
ListNode* pre = &dummy;
while (cur) {
ListNode* next = cur->next;
while (pre->next && pre->next->val < cur->val) {
pre = pre->next;
}
cur->next = pre->next;
pre->next = cur;
cur = next;
}
return dummy.next;
}
};
```
选择排序:
反复从还未排好序的节点中找到最小值,并将其放到已排序部分的末尾。选择排序的时间复杂度为O(N^2),空间复杂度为O(1)。
```cpp
class Solution {
public:
ListNode* selectionSortList(ListNode* head) {
if (!head || !head->next) return head;
ListNode* minNode = head;
ListNode* cur = head->next;
while (cur) {
if (cur->val < minNode->val) {
minNode = cur;
}
cur = cur->next;
}
if (minNode != head) {
int temp = minNode->val;
minNode->val = head->val;
head->val = temp;
}
return head;
}
};
```
总结
归并排序:时间复杂度O(Nlogn),空间复杂度O(N),是链表排序的最佳方法。
插入排序:时间复杂度O(N^2),空间复杂度O(1),适用于小规模数据。
选择排序:时间复杂度O(N^2),空间复杂度O(1),适用于小规模数据。
根据具体