代码写的有点烂,希望能表达自己的意思。欢迎各位提意见~~
/*
author:JTR@BNU
思路:使用归并排序的思想,使用逐步增加步长的方法将整个链表的排序逐步从最简单的长度为1的两个链表归并,直到最终长度达到链表长度
*/
/*
Sort a linked list in O(n log n) time using constant space complexity.
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
struct ListNode {
int val;
ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};
class Solution {
public:
ListNode *sortList(ListNode *head) {
if (head == NULL || head->next == NULL)
{
return head;
}
int step = 1, length = 0; //step是控制归并排序每次增长的步长,length是所给链表的长度
ListNode * firstList, *secondList;//f分别指向两个需要归并排序的链表头
//下面是计算链表长度
firstList = head;
while (firstList)
{
length++;
firstList = firstList->next;
}
//整个控制步长增长的循环
while (length - step > 0)
{
ListNode * ne = head; //记录下次第一个链表开始的地方,初始是整个链表的头
ListNode * lastHead = new ListNode(0);//用于指向每次归并排序得到的排好序的头,是一个临时节点,最终应该Del
ListNode * newHead = lastHead; //记录每次归并排序最后一个节点,为了和下一个归并排序之后的链表结合
while (ne)//一直到整个链表的最后
{
firstList = ne;
secondList = firstList;
int tem = step, len1 = 0, len2 = 0;
while (tem && secondList->next != NULL)
{
secondList = secondList->next;
tem--;
}
len1 = step - tem;
ne = secondList;
while (ne && len2 < step)
{
ne = ne->next;
len2++;
}
ListNode * h = combinateList(firstList, secondList, len1, len2);
lastHead->next = h;
lastHead = h;
tem = 0;
while (tem<len1+len2-1)
{
lastHead = lastHead->next;
tem++;
}
}
lastHead->next = NULL; //很重要,最后一个归并排序的链表需要设置成为链表最终的结束位置,
//其实每次都需要,但是中间归并排序这个尾巴都会被复制为下一个归并排序结果的头
head = newHead->next;//重新将目前部分排好序的链表头返回到下次循环的头
step *= 2;//增加步长
}
delete ne;
return head;
}
ListNode * combinateList(ListNode * firstList, ListNode * secondList, int firstLength, int secondLength)
{
if ((firstList == NULL && secondList == NULL) || firstLength < 0 || secondLength < 0)
{
return NULL;
}
if (firstList != NULL && secondList == NULL)
{
return firstList;
}
if (firstList == NULL && secondList != NULL)
{
return secondList;
}
ListNode * result, *cur;
ListNode * firstHead = firstList, *secondHead = secondList;
int step1 = 0, step2 = 0;
if (firstHead->val < secondHead->val)
{
result = firstHead;
firstHead = firstHead->next;
step1++;
}
else
{
result = secondHead;
secondHead = secondHead->next;
step2++;
}
cur = result;
while (firstHead !=NULL && secondHead != NULL && step1 < firstLength && step2 < secondLength)
{
if (firstHead->val < secondHead->val)
{
cur->next = firstHead;
cur = cur->next;
firstHead = firstHead->next;
step1++;
}
else
{
cur->next = secondHead;
cur = cur->next;
secondHead = secondHead->next;
step2++;
}
}
if (step1 != firstLength && step2 != secondLength)
{
return NULL;
}
if (step1 == firstLength)
{
cur->next = secondHead;
}
else
{
cur->next = firstHead;
}
return result;
}
};