优化快速排序的单链表链表、快速

2023-09-10 23:22:06 作者:青春就应该放肆

我的工作实现快速排序功能,单链表排序。我会什么算法使用做到这一点?为一个链接列表,将采取的,而不是通常的O(1),用于阵列最坏情况为O(N)的每一个比较。那么,什么会最坏情况下的复杂性有多大?

要总结,我需要什么样的修改做出的快速排序算法,以取得最佳的排序算法,什么是算法的最坏情况下的复杂性?

谢谢!

我有以下的实现:

 公共静态SingleLinkedList快速排序(SingleLinkedList列表,SLNode第一,SLNode最后一个)
{
    如果(第一= NULL和放大器;!&放大器;最后!= NULL)
    {
        SLNode P =分区(列表中,第一个,最后一个);
        快速排序(列表中,第一页);
        快速排序(列表,p.succ,最后一个);
    }
    返回列表;
}

公共静态SLLNode分区(SinlgleLinkedList列表,SLNode第一,SLNode最后一个)
{

    SLNode P =第一;
    SLNode PTR = p.succ;

    而(PTR!= NULL)
    {
        如果(ptr.data.compareToIgnoreCase(p.data)℃,)
        {
            字符串支点= p.data;
            p.data = ptr.data;
            ptr.data = p.succ.data;
            p.succ.data =支点;
            P = p.succ;
        }
        PTR = ptr.succ;
    }
    返回磷;
}
 

解决方案

归并更自然实现的链表,但你的可以的做快速排序非常漂亮。下面是一个是C,我在一些应用中使用。

这是一个普遍的神话,你不能有效地名单做快速排序。这仅仅是不正确的,但认真执行是必需的。

快速排序及其拓展优化 单向快速排序 单链表的快速排序

要回答你的问题,快速排序算法的名单在本质上是相同的阵列。挑选一个枢轴(低于code使用的列表的头),分割成绕枢轴两个列表,然后这些列表递归进行排序,并与枢轴在中间追加的结果。什么是有点非显而易见的是,追加操作可以在没有额外传过来的名单做,如果你的列表中添加一个参数被追加为 - 是的排序结果的尾巴。在基本情况下,追加这个列表不需要工作。

事实证明,如果比较便宜,归并往往会运行得更快一点,因为快速排序花更多的时间与指针摆弄。但是,如果比较昂贵,然后快速排序通常运行得更快,因为它需要他们少。

如果节点*名单是初始列表的头,那么你可以用

排序

  QS(列表,NULL,&安培;清单);
 

下面是排序code。注意它的一大块是已排序列表的优化。这种优化可以,如果这些情况都是罕见的被删除。

 无效QS(NODE * HD,NODE * TL,NODE ** RTN)
{
    INT非线性光学,NHI;
    NODE *卤味,*您好,* Q,* P;

    / *不变:返回头排序与'TL'追加。 * /
    而(高清!= NULL){

        非线性光学= NHI = 0;
        LO =喜=​​ NULL;
        Q =高清;
        P = HD->接着,

        / *开始优化O(n)的行为对排序和反向-的排序列表* /
        而(P = NULL和放大器;!&安培; LEQ(P,HD)){
            HD->接下来=喜;
            喜=高清;
            ++ NHI;
            HD = P;
            p值=对 - >接着,
        }

        / *如果整个列表呈上升趋势,我们就大功告成了。 * /
        如果(P == NULL){
            * RTN =高清;
            HD->接下来=喜;
            Q->接下来= TL;
            返回;
        }
        / *结束优化。如果需要的话可以被删除。 * /

        / *分区和计数的大小。 * /
        而(P!= NULL){
            Q =对 - >接着,
            如果(LEQ(对,HD)){
                P->接下来= LO;
                罗= P;
                ++非线性光学;
            } 其他 {
                P->接下来=喜;
                喜= P;
                ++ NHI;
            }
            P = Q;
        }

        / *岑参建立不变高清的子列表,
           首先选择最短的列表来限制堆栈。 * /
        如果(NLO< NHI){
            QS(LO,高清,RTN);
            RTN =安培; HD  - >接着,
            HD =喜; / *被淘汰尾递归调用。 * /
        } 其他 {
            QS(喜,TL,和放大器; HD  - >接着);
            TL =高清;
            HD = LO; / *被淘汰尾递归调用。 * /
        }
    }
    / *复发的基本情况。不变是很容易在这里。 * /
    * RTN = TL;
}
 

I am working on implementing a quicksort function to sort singly linked lists. What algorithm would I have to use to accomplish this ? For a linked list it would take worst case O(N) for each comparison, instead of the usual O(1) for arrays. So what would the worst case complexity be ?

To sum up, what modifications do I need to make to the quicksort algorithm to have an optimal sorting algorithm and what would be the worst case complexity of the algorithm ?

Thanks!

I have an implementation below:

public static SingleLinkedList quickSort(SingleLinkedList list, SLNode first, SLNode last)
{
    if (first != null && last != null)
    {
        SLNode p = partition(list, first, last) ;
        quickSort(list,first,p) ;
        quickSort(list,p.succ, last) ;
    }
    return list ;
}

public static SLLNode partition(SinlgleLinkedList list, SLNode first, SLNode last)
{

    SLNode p = first ;
    SLNode ptr = p.succ ;

    while (ptr!=null)
    {
        if (ptr.data.compareToIgnoreCase(p.data)<0)
        {
            String pivot = p.data ;
            p.data =  ptr.data ;
            ptr.data = p.succ.data ;
            p.succ.data = pivot ;
            p = p.succ ;
        }
        ptr = ptr.succ ;
    }
    return p ;
}

解决方案

Mergesort is more natural to implement for linked lists, but you can do quicksort very nicely. Below is one in C I've used in several applications.

It's a common myth that you can't do Quicksort efficiently with lists. This just isn't true, although careful implementation is required.

To answer your question, the Quicksort algorithm for lists is essentially the same as for arrays. Pick a pivot (the code below uses the head of the list), partition into two lists about the pivot, then recursively sort those lists and append the results with pivot in the middle. What is a bit non-obvious is that the append operation can be done with no extra pass over the list if you add a parameter for a list to be appended as-is at the tail of the sorted result. In the base case, appending this list requires no work.

It turns out that if comparisons are cheap, mergesort tends to run a little faster because quicksort spends more time fiddling with pointers. However if comparisons are expensive, then quicksort often runs faster because it needs fewer of them.

If NODE *list is the head of the initial list, then you can sort it with

qs(list, NULL, &list);

Here is the sort code. Note a chunk of it is an optimization for already-sorted lists. This optimization can be deleted if these cases are infrequent.

void qs(NODE * hd, NODE * tl, NODE ** rtn)
{
    int nlo, nhi;
    NODE *lo, *hi, *q, *p;

    /* Invariant:  Return head sorted with `tl' appended. */
    while (hd != NULL) {

        nlo = nhi = 0;
        lo = hi = NULL;
        q = hd;
        p = hd->next;

        /* Start optimization for O(n) behavior on sorted and reverse-of-sorted lists */
        while (p != NULL && LEQ(p, hd)) {
            hd->next = hi;
            hi = hd;
            ++nhi;
            hd = p;
            p = p->next;
        }

        /* If entire list was ascending, we're done. */
        if (p == NULL) {
            *rtn = hd;
            hd->next = hi;
            q->next = tl;
            return;
        }
        /* End optimization.  Can be deleted if desired. */

        /* Partition and count sizes. */
        while (p != NULL) {
            q = p->next;
            if (LEQ(p, hd)) {
                p->next = lo;
                lo = p;
                ++nlo;
            } else {
                p->next = hi;
                hi = p;
                ++nhi;
            }
            p = q;
        }

        /* Recur to establish invariant for sublists of hd, 
           choosing shortest list first to limit stack. */
        if (nlo < nhi) {
            qs(lo, hd, rtn);
            rtn = &hd->next;
            hd = hi;        /* Eliminated tail-recursive call. */
        } else {
            qs(hi, tl, &hd->next);
            tl = hd;
            hd = lo;        /* Eliminated tail-recursive call. */
        }
    }
    /* Base case of recurrence. Invariant is easy here. */
    *rtn = tl;
}