【问题标题】:Alphabetically sort in Linked Lists in C?在C中的链接列表中按字母顺序排序?
【发布时间】:2016-11-13 18:06:52
【问题描述】:

我正在尝试按字母顺序对这个链接列表中的名称进行排序,但我不确定哪种方法是正确的。我创建了一个方法来比较列表中的名称并每次更新我的当前指针。我不断收到错误。有人可以建议一种更好的方法来对名称进行排序吗?我是 C 新手,我正在努力寻找更好的方法来实现这一点。任何帮助将不胜感激。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define HOW_MANY  7

char *names[HOW_MANY] = { "Ben", "Chris", "RDJ", "Mark", "Scarlet", "Samuel", "Tom" };
int ages[HOW_MANY] = { 22, 24, 50, 26, 18, 32, 24 };

/* declare your struct for a person here */
struct person {
    char *name;
    int age;
    struct person *next;
};

static struct person *compare_people(struct person *headptr, struct person *headptr) {
    int didSwap = 1, limit = HOW_MANY - 1;
    struct person *temp;
    struct person *previous = headptr;
    struct person *new = headptr -> next;

    while (didSwap) {
        didSwap = 0;
        for (int i = 0; i < limit; i++) {
            if (strcmp(previous->name, new->name) > 0) {
                temp = previous;
                previous = new;
                new = temp;
                didSwap = 1;
            }
        }
        limit--;
    }
    return temp;
}

static struct person *insert_sorted(struct person *headptr, char *name, int age) {
    struct person *ptr;
    // Allocate heap space for a record
    ptr = malloc(sizeof(struct person));
    if (ptr == NULL)
        abort();
    // Assign to structure fields
    ptr->name = name;
    ptr->age = age;
    ptr->next = NULL;

    if (headptr == NULL) {
        ptr->next = headptr;
        headptr = ptr;
    } else {
        struct person *currptr = headptr;

        while (currptr != NULL) {
            currptr = compare_people(headptr, headptr);
        }
        headptr = currptr;
    }
    return headptr;
}

int main(int argc, char **argv) {
    // initialise the pointer  to be empty
    struct person *headptr = NULL;

    // To insert all the info in the array
    for (int i = 0; i < HOW_MANY ; i++) {
        headptr = insert_sorted(headptr, names[i], ages[i]);
    }

    struct person *current = headptr;
    while (current != NULL) {
        printf("The person's name is %s and the age is %d.\n", current->name, current->age);
        current = current->next;
    }
    return 0;
}

【问题讨论】:

  • 检查列表的开头。如果该元素的字典顺序大于您要插入的单词,请检查下一个元素。重复。如果您找到一个在字典上比您的单词少的单词,则在此处插入该单词。
  • 链表很自然地适合归并排序。见stackoverflow.com/questions/35614098/…

标签: c sorting


【解决方案1】:

您的方法太复杂了:比较函数执行某种排序,插入函数也执行。比较函数应该返回一个int,其值为负、0 或正,如strcmp(),并且insert_sorted 应该使用简单的迭代方法将新的person 插入到列表中的适当位置。

这是一个更简单的版本:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define HOW_MANY  7

char *names[HOW_MANY] = { "Ben", "Chris", "RDJ", "Mark", "Scarlet", "Samuel", "Tom" };
int ages[HOW_MANY] = { 22, 24, 50, 26, 18, 32, 24 };

/* declare your struct for a person here */
struct person {
    char *name;
    int age;
    struct person *next;
};

static int compare_people(const struct person *a, const struct person *b) {
     return strcmp(a->name, b->name);
}

static struct person *insert_sorted(struct person *headptr, char *name, int age) {
    // Allocate heap space for a record
    struct person *ptr = malloc(sizeof(struct person));
    if (ptr == NULL) {
        abort();
    }

    // Assign to structure fields
    ptr->name = name;
    ptr->age = age;
    ptr->next = NULL;

    struct person **pp = &headptr;
    while (*pp != NULL && compare_people(ptr, *pp) >= 0) {
        pp = &(*pp)->next;
    }
    ptr->next = *pp;
    *pp = ptr;

    return headptr;
}

int main(int argc, char **argv) {
    // initialise the list to be empty
    struct person *headptr = NULL;

    // To insert all the info in the array
    for (int i = 0; i < HOW_MANY; i++) {
        headptr = insert_sorted(headptr, names[i], ages[i]);
    }

    struct person *current = headptr;
    while (current != NULL) {
        printf("The person's name is %s and the age is %d.\n", current->name, current->age);
        current = current->next;
    }
    return 0;
}

编辑: 下面是带有简单指针的替代版本。您可以看到我需要对空列表和开头的插入进行特殊情况。

static struct person *insert_sorted(struct person *headptr, char *name, int age) {
    // Allocate heap space for a record
    struct person *ptr = malloc(sizeof(struct person));
    if (ptr == NULL) {
        abort();
    }
    ptr->name = name;
    ptr->age = age;
    ptr->next = NULL;

    if (headptr == NULL || compare_people(ptr, headptr) < 0) {
        ptr->next = headptr;
        return ptr;
    } else {
        struct person *cur = headptr;
        while (cur->next != NULL && compare_people(ptr, cur->next) >= 0) {
            cur = cur->next;
        }
        ptr->next = cur->next;
        cur->next = ptr;
        return headptr;
    }
}

【讨论】:

  • 如果你想按年龄升序排序,只需将compare_people()函数中的return strcmp(a-&gt;name, b-&gt;name);替换为return (a-&gt;age &gt; b-&gt;age);...
  • @J.Piquard:为了保持一致,compare_age 应该返回签名状态; return (a-&gt;age &gt; b-&gt;age) - (a-&gt;age &lt; b-&gt;age);
  • @chqrlie 你能解释一下吗..因为我是 C 新手。“struct person currptr”与“struct person currptr”之间是否有主要区别?或者我可以使用这个`struct person *currptr = headptr; while (currptr != NULL && compare_people(ptr,currptr) > 0) { currptr = currptr -> next; } ptr -> 下一个 = currptr; currptr = ptr; `
  • 抱歉,我无法让缩进正常工作?
  • @chqrlie 做一个指针的指针然后赋值给headptr的地址是不是很重要?我不能只使用 currptr 的指针并将其分配给 headptr 吗?
猜你喜欢
  • 2020-03-29
  • 2017-05-19
  • 1970-01-01
  • 2020-04-07
  • 1970-01-01
  • 1970-01-01
  • 2021-08-10
  • 2015-12-08
相关资源
最近更新 更多