【问题标题】:Sort in alphabetical order a List in c按字母顺序排序 c 中的列表
【发布时间】:2017-05-19 08:16:07
【问题描述】:

您好,我正在编写一个管理学生列表的程序,我正在使用一个列表,每个元素的描述如下:

struct student
{
    char lastname[50];
    char name[50];
    char date_of_birth[50];
    char height[50];
    struct student *next;
};

struct student *root=0; //this is the root node

这就是我向列表中添加元素的方式:

void add_element(struct student **root, char lastname[50], char name[50], char date_of_birth[50], char height[50])
{
    if(*root == 0)
    {
        *root = malloc(sizeof(struct student));
         strcpy((*root)->lastname,lastname);
         strcpy( (*root)->name,name);
         strcpy( (*root)->date_of_birth,date_of_birth);
         strcpy( (*root)->height,height);

        (*root)->next = 0;
    }
    else
    {
        add_element(&(*root)->next,lastname,name,date_of_birth,height);
    }
} 

我还写了 2 个函数,一个是读取文件,另一个是写入文件,文件包含所有学生,一切正常,但我需要一个函数按姓氏字母顺序对所有元素进行排序,我试着写了一个,但它不起作用,它一直在崩溃。

我尝试了很多东西都没有成功,这是一次尝试,但没有成功:-(

请帮帮我

void sort(struct student *head)
{
    struct student **current;
    struct student *tmp;

    for(current = &head ; *current !=NULL ; current = (*current)->next)
    {
        if((*current)->next == NULL)
        {
            break;
        }
        switch(strcmp((*current)->lastname,(*current)->next->lastname))
        {
            case 0:
            {
                printf("user not valid");
                break;
            }

            case 1:
            {
                tmp = *current;
                *current = (*current)->next;
                (*current)->next = tmp;
                break;
            }
        }
    }
}

【问题讨论】:

  • Hmmmm char height[50]; --> 50 意味着非常个高的学生的可能性。 ;-)
  • 什么是struct alunno? IAC,推荐*root = malloc(sizeof(struct alunno)); --> *root = malloc(sizeof *(*root)); 并发布 true 代码。
  • 您是否注意到您收到的编译器警告?例如:current = (*current)->next 应该产生警告,因为 current 是 student ** 而 (*current)->next 是 student *。
  • 注意:对于N学生,要添加另一个add_element()的学生,该函数可能会递归N次。如果N 很大,那么这肯定是非展开代码的问题。建议一个非递归的解决方案。
  • 不要在开关中使用strcmp 的结果。结果保证为0,或任何负值或正值 - 不是具体的 1 或 -1。

标签: c list sorting alphabetical alphabetical-sort


【解决方案1】:

在包含来自 cmets 的评论以更正建议的源代码后,对链表进行排序的算法缺少一些步骤。至少,要对链表进行排序,必须有两个循环。对于两个嵌套循环,使用struct student **current 访问的选择会很复杂。

这是另一个使用优化的qsort()函数的强大排序功能。

第一步 - 在显示函数之前,要对列表进行排序,需要修改root指针。

第一种方法,用于add_element(),通过发送地址 指针。

void sort(struct student **root)
{
...
}

第二种方法,返回修改后的root。

struct student *sort(struct student *root)
{
...
    return (root);
}

第 2 步 - 使用 qsort() 快速排序函数的函数 sort()。

该方法分配一个临时指针数组,以便有一个固定大小的元素进行排序。

  1. 第一个循环需要知道要排序的指针个数(如果小于2,则不需要排序);
  2. 分配struct student *的数组后,对链表的每一项使用循环填充数组;
  3. 使用自定义比较函数node_compare()调用qsort()函数(见下一步);
  4. 通过强制struct student *next 的值(第一个是*root,最后一个指向NULL)来恢复带有排序指针的链表。
  5. 释放struct student *的临时数组;

就是这样。

//
void sort(struct student **root)
{
    struct student *tmp;
    struct student **array;
    int i,icount;

    // number of nodes to be sorted
    for(tmp = *root,icount = 0;tmp!=NULL;tmp = tmp->next,icount++);
    if (icount<2) {
        // no sort needed
        return;
    }

    // allocate an array of pointers
    array = (struct student **)malloc(icount*sizeof(struct student *));
    // push linked-list into array of pointers
    for(tmp = *root,icount = 0;tmp!=NULL;tmp = tmp->next,icount++) {
        array[icount]=tmp;
    }

    // quicksort using node_compare() customized function
    qsort(array, icount, sizeof(struct student *), node_compare);

    // pop linked-list from array of pointers
    *root = array[0];
    (*root)->next = NULL;
    for(tmp = *root,i = 1;i<icount;i++) {
        tmp->next = array[i];
        array[i]->next = NULL;
        tmp = tmp->next;
    }
    // free the allocated array of pointer
    free(array);
}
//

第 3 步 - 比较函数 node_compare() 需要与 qsort()。

该函数应像strcmp() 那样返回一个带符号的比较。

int node_compare(const void * a, const void * b)
{
    // restore node pointers
    struct student *node_a = *((struct student **)a);
    struct student *node_b = *((struct student **)b);

    if (node_b==NULL) return (-1); // force 'node_a'
    if (node_a==NULL) return (+1); // force 'node_b'
    // use the strcmp() function
    return (strcmp(node_a->lastname,node_b->lastname));
}

增强功能 - 因为add_element() 使用了不符合长链表的递归调用,所以这里有一个非常简单的非递归算法。

如果递归算法将大小限制在几个世纪 元素,建议的元素已经过 100,000 个元素(40Mb 链表),随机生成并排序。

void add_element(struct student **root, char lastname[50], char name[50], char date_of_birth[50], char height[50])
{
    struct student **current;

    for(current = root; *current !=NULL ; current = &((*current)->next));
    *current = (struct student *)malloc(sizeof(struct student));
    strcpy((*current)->lastname,lastname);
    strcpy( (*current)->name,name);
    strcpy( (*current)->date_of_birth,date_of_birth);
    strcpy( (*current)->height,height);

    (*current)->next = NULL;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-03-29
    • 2018-09-15
    • 2013-05-02
    • 2014-02-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多