使用C中的合并排序或快速排序对很长的链接列表进行排序

亚瑟

我必须执行我被困住的著名的LS命令,因为对于需要排序的每个文件夹(ASCII,时间或反向顺序),我都会得到一个很长的Linked-List

这是我的链表结构,

 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;
    }
}

我的问题是,这一步非常慢。

我想实现另一种排序算法Merge sort或Quicksort,我不知道哪种算法最适合我的情况

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

谢谢你的帮忙!

chqrlie

您的排序代码不正确:您交换了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;
}

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章