【问题标题】:Quick Sort on a Linked List with a random pivot in C在 C 中使用随机枢轴对链表进行快速排序
【发布时间】:2012-03-11 04:53:15
【问题描述】:

我花了很多时间试图为一堂课解决这个问题,但我已经结束了。我找到了很多关于数组和其他选择轴的方法的资源,但我只是到头了,我真的要疯了,任何帮助都会非常感激,你无法想象。

#include <stdlib.h>     /*and, malloc*/
#include <stdio.h>      /*printf*/


struct listnode {

    struct listnode *next;
    long value;
};

/*Finds length of list, which is usefull in selecting a random pivot*/
int ListLength (struct listnode *list)
{
    struct listnode *temp = list;

    int i=0;
    while(temp!=NULL)
    {
        i++;
        temp=temp->next;

    }
    return i;
}

/*Prints list*/
void printList(struct listnode *list)
{   
    struct listnode *node;
    node=list;
    printf("\nList Values\n");
    while(node!=NULL)
    {
        printf("%2lo ", node->value);
        node=node->next;
    }
}
/*Creates a list of desired length*/
struct listnode *createList(int lengthOfList)
{
    long i; 
    struct listnode *node, *space;
    space =  (struct listnode *) malloc( lengthOfList*sizeof(struct listnode));
    for( i=0; i< lengthOfList; i++ )
    {  (space + i)->value = 2*((17*i+1)%lengthOfList);
       (space + i)->next = space + (i+1);
    }

    (space+(lengthOfList-1))->next = NULL;
    node = space;

    return node;
}

/*Prof Brass's test*/
void Brass_test(struct listnode *list)
{
    int i;
    printf("\nChecking sorted list\n");
    for( i=0; i < 100; i++)
    {  
        if( list == NULL )
        { 
            printf("List ended early\n"); exit(0);
        }
        if( list->value != 2*i )
        {  
            printf("Node contains wrong value\n"); exit(0);
        }
        list = list->next;
   }
   printf("Sort successful\n");
}

/*Selects a random pivot point*/
struct listnode *SelectPivot(struct listnode *list)
{

    int k, n, i = 0;
    n = ListLength(list);


    struct listnode *pivot=list;

    k=rand()%n;

    for (; i < k; ++i)
    {
        pivot=pivot->next;
    }

    return pivot;
}

// Sorts a list using quicksort algo with random pivot point
struct listnode *Quicksort(struct listnode *list)
{
    // Return NULL list
    if (ListLength(list) <= 1) return list;

    struct listnode *less=NULL, *more=NULL, *next, *endl, *temp=list;

    /*Select a random pivot point*/
    struct listnode *pivot = SelectPivot(list);

    printf("Pivot Value = %lo\n", pivot->value);



    /*Divide & Conquer*/
    while(temp != NULL)
    {

        next = temp->next;

        if(temp->value < pivot->value)
        {
            temp->next = less;
            less = temp;
        }
        else 
        {
            temp->next = more;
            more = temp;

        }
        temp = next;
    }



    less = Quicksort(less);
    more = Quicksort(more);

    // Merge
    if(ListLength(less)!=0)
    {       
        while(endl != NULL)
        {
            endl = less->next;
            less->next = more;
            more = less;
            less = endl;
        }

        return more;        
    }
    else 
    {


        return more;    
    }

}

int main(void)
{
    struct listnode *node;

    node = createList(25);

    printf("Unsorted List\n");
    printList(node);

    printf("\nSorted List\n");
    node =  Quicksort(node);


    printf("\nList Count node %d\n", ListLength(node));
    printList(node);

   /* Brass_test(node);*/




    exit(0);
}

【问题讨论】:

  • 链表上的快速排序是一个不切实际的概念——它确实不是数据结构的合适算法。您可能最好将列表转换为数组,对数组进行排序,然后重新构建列表。其他任何东西都将比普通的快速排序慢得多,因为快速排序基于对数组中任意项目的 O(1) 访问时间,并且使用列表你可以获得对列表中任意项目的 O(N) 访问,所以你的 O(N log N) QuickSort 算法变成 O(N*N log N),比冒泡排序等差。
  • @Jonathan:不正确——快速排序的分区阶段按顺序遍历所有元素。因此,即使您每一步都需要额外的 O(N) 来选择枢轴,但对于列表排序,总体上仍然是 O(N log N)。由于常数因子较低,其他类型可能仍然更有意义。
  • @ChrisDodd 对,对于链表,mergesort 变体很容易实现并且比快速排序更快。
  • 好吧,至少它不使用 C++ ;-) 但是考虑到一开始的额外线性传递,他也可以创建一个带有指针的临时数组,对其进行排序,然后重建列表(再次额外通行证)。恕我直言,可能更快,更健壮。但真正的问题是:链表很漂亮,但如果你需要对它们进行排序,你可能一开始就做错了。并且:对于链表来说,合并排序当然要自然得多。

标签: c sorting random linked-list quicksort


【解决方案1】:

因此,对于那些对代码感兴趣的人来说,这里是问题的解决方案。我只包含了它自己的函数和辅助函数。

干杯,

#include <stdlib.h>     //rand, malloc
#include <stdio.h>      //print
#include <time.h>

struct listnode {

    struct listnode *next;
    long value;
};

//Finds length of list, which is usefull in selecting a random pivot
int ListLength (struct listnode *list)
{
    struct listnode *temp = list;
    int i=0;
    while(temp!=NULL)
    {
        i++;
        temp=temp->next;
    }
    return i;
}

// Selects a random pivot point
struct listnode *SelectPivot(struct listnode *list)
{
    int k, n, i = 0;
    n = ListLength(list);
    struct listnode *pivot=list;
    k=rand()%n;  //
    for (; i < k; ++i)
    {
        pivot=pivot->next;
    }
    return pivot;
}

// Sorts a list using quicksort algo with random pivot point
struct listnode *Quicksort(struct listnode *list)
{
    // Return NULL list
    if (ListLength(list) <= 1) return list;
    struct listnode *less=NULL, *more=NULL, *next, *end, *temp=NULL;

    // Select a random pivot point
    struct listnode *pivot = SelectPivot(list);

    // Remove pivot from list
    while(list !=NULL)
    {
        next = list->next;

        if(list->value != pivot->value)
        {
            list->next=temp;
            temp = list;
        }
        list = next;
    }

    // Divide & Conq
    while(temp != NULL)
    {
        next = temp->next;
        if(temp->value < pivot->value)
        {
            temp->next = less;
            less = temp;
        }
        else 
        {
            temp->next = more;
            more = temp;    
        }
        temp = next;
    }

    // Recursive Calls
    less = Quicksort(less);
    more = Quicksort(more);

    // Merge
    if(less != NULL)
    {
        end = less;
        while(end->next != NULL){
            end=end->next;
            }
        pivot->next=more;
        end->next = pivot;
        return less;        
    }
    else{
        pivot->next = more;
        return pivot;   
    }

}

【讨论】:

    【解决方案2】:

    一个问题是您的合并代码 - 它反转了 less 列表,同时将其添加到 more 列表中,这会导致垃圾。

    【讨论】:

      【解决方案3】:

      在应用快速排序的情况下,最佳做法是始终以 FLOOR(n/2) 作为支点

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-11-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-08-31
        • 1970-01-01
        相关资源
        最近更新 更多