题目:给你链表的头结点 head ,请将其按 升序 排列并返回 排序后的链表 。
要求:在 O(n log n) 时间复杂度和常数级空间复杂度下,对链表进行排序。
- 由于时间复杂度要在o(n log n)内 所以冒泡排序就不在选择范围内了 这里采用归并排序。
- 归并排序分为 迭代法 和 递归法 下面俩种方法的代码都将展示。
- 递归的核心思路就是:二分法
从中间切割 然后左右俩边的一路按中切割到最小单位 然后排序返回
举例 42507163
42507163
4250 7163
42 50 71 63 切割到最小单位排序
24 05 17 36 再合并排序
0245 1376
01234567 - 迭代法是在链表长度内进行切割
先 2 2比较完后排序 再 4 4比较 再8 8…
举例: 42507163
先按42 50 71 63切割后排序得 24 05 17 36
再按2405 1736切割后排序 得 0245 1367
最后再按02451367比较排序 得 01234567
struct ListNode {
int val;
struct ListNode *next;
};
struct ListNode* FindLinkMid(struct ListNode* head)
{
if (head == NULL) {
return head;
}
struct ListNode* fast = head->next;
struct ListNode* slow = head;
while (fast != NULL && fast->next != NULL) {
fast = fast->next->next;
slow = slow->next;
}
return slow;
}
struct ListNode* Merger(struct ListNode* left, struct ListNode* right)
{
struct ListNode* head = (struct ListNode *)malloc(sizeof(struct ListNode));
struct ListNode* temp = head;
head->next = NULL;
while (left != NULL && right != NULL) {
if (left->val <= right->val) {
temp->next = left;
left = left->next;
} else {
temp->next = right;
right = right->next;
}
temp = temp->next;
}
if (left != NULL) {
temp->next = left;
}
if (right != NULL) {
temp->next = right;
}
return head->next;
}
struct ListNode* MergerSort_Recursion(struct ListNode* head)
{
if (head == NULL || head->next == NULL) {
return head;
}
struct ListNode* mid = FindLinkMid(head);
struct ListNode* next = mid->next;
mid->next = NULL;
struct ListNode* left = MergerSort_Recursion(head);
struct ListNode* right = MergerSort_Recursion(next);
return Merger(left, right);
}
struct ListNode* Cut_List(struct ListNode* head, int cut)
{
while (head!=NULL && --cut) {
head = head->next;
}
if (head == NULL) {
return NULL;
}
struct ListNode*temp = head->next;
head->next = NULL;
return temp;
}
struct ListNode* MergerSort_Iteration(struct ListNode* head)
{
if (head == NULL || head->next == NULL) {
return head;
}
int len = 1;
struct ListNode* temp = head;
while(temp->next != NULL) {
len++;
temp = temp->next;
}
struct ListNode* dummy = (struct ListNode *)malloc(sizeof(struct ListNode));
dummy->next = head;
for (int cut = 1; cut < len; cut<<=1) {
struct ListNode* curr = dummy->next;
struct ListNode* tail = dummy;
while (curr != NULL) {
struct ListNode* left = curr;
struct ListNode* right = Cut_List(left, cut);
curr = Cut_List(right, cut);
tail->next = Merger(left, right);
while(tail->next != NULL) {
tail = tail->next;
}
}
}
return dummy->next;
}