单链表排序

摘自: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;
}

  

posted @ 2022-04-14 10:36  simon1024  阅读(31)  评论(0编辑  收藏  举报