单链表排序
摘自:https://blog.csdn.net/bigtree_3721/article/details/82945924
一般人见到这种题目,立马就会想到指针交换。是的,大家被指针交换的题目做多了,形成思维定势了。对于这道题,我们完全可以利用值交换来达到排序的目的。当然,怎么值交换?
很多人得第一想法就是选择排序,这个木有问题,不过它的复杂度为O(n^2);
有木有更好一点的方法呢?归并,不错,归并确实能将复杂度降到O(nlogn)不过,它是是链表交换的形式,我们这里提到的是要用值交换的形式。
还有别的方法吗?对了,快排!怎么会是快排?快排不是需要一个指针指向头,一个指针指向尾,然后两个指针相向运动并按一定规律交换值,最后找到一个支点使得支点左边小于支点,支点右边大于支点吗?是滴,木有错,不过问题出来了。如果是这样的话,对于单链表我们没有前驱指针,怎么能使得后面的那个指针往前移动呢?所以这种快排思路行不通滴。
如果我们能使两个指针都往next方向移动并且能找到支点那就好了。怎么做呢?接下来我们使用快排的另一种思路来解答。我们只需要两个指针p和q,这两个指针均往next方向移动,移动的过程中保持p之前的key都小于选定的key,p和q之间的key都大于选定的key,那么当q走到末尾的时候便完成了一次支点的寻找。
#include "LinkList.h"
void Swap(LinkList* node0, LinkList* node1) {
int temp = node0->val;
node0->val = node1->val;
node1->val = temp;
}
void QuickSort(LinkList* head, LinkList* tail) {
if (head == NULL || head == tail) {
return;
}
int temp = head->val;
LinkList* p = head;
LinkList* pre = head;
LinkList* q = head;
while(q != tail) {
q = q->next;
if (q == NULL) {
break;
}
if (q->val < temp) {
pre = p;
p = p->next;
Swap(p, q);
}
}
Swap(head, p);
QuickSort(head, pre);
QuickSort(p->next, tail);
}
int main() {
int a[] = {57, 68, 59, 52, 72, 28, 96, 33, 24};
int len = sizeof(a) / sizeof(a[0]);
LinkList* list = LinkListUtil::create(a, len);
LinkListUtil::print(list);
QuickSort(list, NULL);
LinkListUtil::print(list);
return 0;
}
浙公网安备 33010602011771号