使用C

时间:2019-03-04 07:31:27

标签: c sorting linked-list quicksort mergesort

我必须执行著名的LS命令 我之所以陷入困境,是因为对于每个我要排序的文件夹(ASCII,时间或反向顺序),最后的链接列表都非常长

这是我的链表结构,

 typedef struct     s_list
{
    void            *content;
    size_t          content_size;
    struct s_list   *next;
}                   t_list

void *content里面放了我的Ls结构,

typedef struct      s_dir
{
    unsigned int    i;
    quad_t          blocks;
    char            *pathname;
    char            *name;
    ino_t           ino;
    uint8_t         type;
    uint16_t        mode;
    unsigned char   nlink;
    char            *usrname;
    char            *grpname;
    long long       size;
    time_t          time;
    struct s_dir    *rec;
    struct s_dir    *next;
    int             error;
}                   t_dir

我目前正在使用此功能对列表进行排序。

static void             sort_ascii(t_list **head)
{
    t_dir   *rep;
    t_list  *curr;
    void    *tmp;
    t_dir   *rep_next;

    curr = *head;
    while (curr && curr->next && (rep = (t_dir *)curr->content)
            && (rep_next = (t_dir *)curr->next->content))
    {
        if (ft_strcmp(rep->pathname, rep_next->pathname) > 0)
        {
            tmp = curr->content;
            curr->content = curr->next->content;
            curr->next->content = tmp;
            curr = *head;
        }
        curr = curr->next;
    }
}

我的问题是,这个速度非常慢。

我想实现另一种排序算法 合并排序或快速排序,我不知道哪种方式最适合我的情况

我根本不知道如何实现这些排序方法 对我来说是全新的。

感谢您的帮助!

1 个答案:

答案 0 :(得分:2)

您的排序代码不正确:您交换了content字段,但没有交换content_size。您应该通过更新列表元素next和更新*head参数来对列表元素进行排序。

您的方法具有二次方复杂度,即使不是更糟。相反,您应该使用 O(N.log(N))的时间复杂度要低得多的mergesort。

这是一个示例(自上而下的合并排序):

/* return the comparison status: 0 for equal, <0 if a < b, >0 if a>b */
int compare_ascii(t_list *a, t_list *b) {
    return ft_strcmp(((t_dir *)a->content)->pathname, ((t_dir *)b->content)->pathname);
}

t_list *merge(t_list *a, t_list *b, int (*cmp)(t_list *a, t_list *b)) {
    t_list *head = NULL;  /* head of the merged list */
    t_list **r = &head;   /* pointer to the node link */
    if (a && b) {
        for (;;) {
            if ((*cmp)(a, b) <= 0) {
                /* link the head node of list a */
                *r = a;
                r = &a->next;
                a = a->next;
                if (!a)
                    break;
            } else {
                /* link the head node of list b */
                *r = b;
                r = &b->next;
                b = b->next;
                if (!b)
                    break;
            }
        }
    }
    /* link the remaining part of a or b if any */
    *r = (a == NULL) ? b : a;
    return head;
}

t_list *mergesort(t_list *p, int (*cmp)(t_list *a, t_list *b)) {
    t_list *a, *b, *last = NULL;
    /* find the middle with 2 finger method: a moves twice as fast as b */
    for (a = b = p; a && a->next; a = a->next->next, b = b->next)
         last = b;
    if (last == NULL) {
        /* empty list or single element */
        return p;
    }
    /* split in the middle (before b) */
    last->next = NULL;
    /* sort each half and merge the sorted sublists */
    return merge(mergesort(p, cmp), mergesort(b, cmp), cmp);
}

void sort_ascii(t_list **head) {
    *head = mergesort(*head, compare_ascii);
}

rcgldr 所述,自下而上的合并排序通常更快,因为它不需要扫描列表来查找中间元素,由于缓存不匹配,这可能会很昂贵。与此相对的是,它可能执行更多比较,但时间复杂度为 O(N.log(N)),并且不是递归的。

这是mergesort的一种版本,使用自下而上的合并排序方式:

t_list *mergesort(t_list *head, int (*cmp)(t_list *a, t_list *b)) {
    t_list *array[32]; // sorted sublists: array[i] has 2**i length if not null
    t_list *result = head;
    int i, top = 0;

    // merge nodes into array
    while (result != NULL) {
        t_list *next = result->next;
        result->next = NULL;
        // merge sorted sublists by increasing power of 2 sizes
        for (i = 0; i < top && array[i] != NULL; i++) {
            result = merge(array[i], result, cmp);
            array[i] = NULL;
        }
        // store the merged list, update top, do not go past end of array
        if (i == top) {
            if (top < 32)
                top++;
            else
                i--;
        }
        array[i] = result;
        result = next;
    }
    // merge all sorted sublists into single list
    result = NULL;
    for (i = 0; i < top; i++) {
        result = merge(array[i], result, cmp);
    }
    return result;
}
相关问题