单链表排序
摘自: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; }