您的位置:首页 > 其它

leetcode之链表类之链表排序-----147/148. 链表快速排序 链表插入排序

2017-09-30 16:43 537 查看
1、OJ148链表快速排序

和数组的快排完全相同,dfs分治,过程也一样,唯一多了的是,在计算出partition点j后,对后半部的递归需要做"partition点和end点是否已经相同"的判断,这是在end点已经是极大/小值时,会导致partition点j也走到end点,在数组快排可以通过"if (start >= end)"过滤,对于单链表则必须在这里提前判断出来,避免进行起点在终点后面的递归

快排的最大好处是空间复杂度符合题意的常数空间复杂度,而归并则需要O(N)空间复杂度,堆本身是数组实现,对链表进行堆排本质上是重载比较运算符,但也需要O(N)空间复杂度。

代码:

ListNode *findtail (ListNode *head) {
while (head && head->next) {
head = head->next;
}

return head;
}

void qsort (ListNode *head, ListNode *tail) {
if (head == tail) {
return;
}

int flagval = tail->val;
ListNode *j = head, *prev = j, *rawst = head;
while (head && head != tail) {
if (head->val < flagval) {
int tmp = head->val;
head->val = j->val;
j->val = tmp;
prev = j;
j = j->next;
}
head = head->next;
}

tail->val = j->val;
j->val = flagval;

head = rawst;
qsort(head, prev);
if (j != tail) {
qsort(j->next, tail);
}
}

ListNode* sortList(ListNode* head) {
if (!head || !head->next) {
return head;
}

ListNode *tail = findtail(head);
qsort(head, tail);
return head;
}


2、OJ147链表插入排序

虽然是插入排序的思想,但是做法和数组插入排序比较不同,核心思路是,将链表分为已排序和未排序两部分开的链表,已排序部分初始只有首元素一个节点,未排序的部分不断的按value大小,插入到已排序部分。

OJ147代码:

class Solution {
public:
ListNode* insertionSortList(ListNode* head) {
if (!head || !head->next) {
return head;
}

ListNode *sorted = head, *unsorted = head->next;
sorted->next = nullptr;

while (unsorted) {
ListNode *cur = unsorted;
unsorted = unsorted->next;

if (sorted->val > cur->val) {
cur->next = sorted;
sorted = cur;
} else {
ListNode *p = sorted, *q = sorted->next;
while (q && q->val < cur->val) {
p = q;
q = q->next;
}

if (q) {
p->next = cur;
cur->next = q;
} else {
p->next = cur;
cur->next = nullptr;
}
}
}

return sorted;
}
};

3、链表归并排序
包括两个链表的归并排序和多个链表的归并排序,这部分虽然也属于排序,但更属于另一类基于归并的相关题,在此不描述
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: