c - 我怎样才能按字母顺序排列这个链表?

标签 c linked-list

我正在编写一个程序,其中输入了姓名和年龄。然后可以调用这些名字并打印出该人的年龄。如果这个人不在列表中,它会将他们的年龄打印为 -1。如果使用列表中已有的新年龄输入名称,则不会添加新条目。目前看来名称是按我输入它们的顺序排序的。如何仅通过更改函数添加的代码来按字母顺序对它们进行排序?此代码可编译并按预期工作,但非字母列表除外。

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

typedef struct person {
    char *name;
    int age;
    struct person *next;
} Person;

void print(Person *); // prints the entire list
Person *add(Person *, char *, int); // adds a new node to the list
int getAge(Person *, char *); // returns the age of the person or -1 if not found

int main(void) {
    char input1[100];
    int input2;
    Person *myList = NULL;
    printf("Enter a person's name (one word) and age : ");
    scanf("%s %d", input1, &input2);
    while (input2 != 0) {
        myList = add (myList, input1, input2);
        printf("\n\nThe list is now : ");   print(myList);
        printf("Enter a name (one word) and age, enter 'xxx' and 0 to exit : ");
        scanf("%s %d", input1, &input2);
    }
    printf("\n\nThe final list is ");   print(myList);
    printf("\n\nEnter the name of a person to look up their age : ");
    scanf("%s", input1);
    while ( strcmp(input1, "xxx") != 0 ) {
        printf("\t%s is %d years old\n", input1, getAge(myList, input1) );
        printf("Enter a name to look up their age or 'xxx' to exit : ");
        scanf("%s", input1);
    }

    return 0;
}

void print(Person *ptr) {
    while (ptr) { printf("[%s-%d] ", ptr->name, ptr->age); ptr = ptr->next; }
    printf("\n");

    return;
}

//adds person to list if the person does not exist already
Person *add(Person *ptr, char *n, int a) {
    Person *newNode = malloc( sizeof(Person) );
    int duplicate = 1;
    Person *dummy = ptr;
    while (dummy) {
        if(strcmp(dummy->name, n) == 0) {
            printf("Name Already Exists in List! Please retry with other name..\n");
            duplicate=-1;
            break;
        }
        else
            dummy = dummy->next;
    }
    if (duplicate!=-1) {
        newNode->name = malloc( strlen(n) + 1 );
        strcpy(newNode->name, n);
        newNode->age = a;
        newNode->next = ptr;
        return newNode;
    }
    duplicate = 1;
    return ptr;
}

//function to find age of the passed person
int getAge(Person *ptr, char *name) {
    while (ptr) {//while loop to traverse entire linked list elements (All persons one by one)
        if(strcmp(ptr->name, name) == 0) //comparing person name in the list with the search key name
            return ptr->age; //if found, returning the age of that person
        else
            ptr = ptr->next; //if not found, check in next node of linked list
    }

    return -1; // if not found, even after visting all nodes, return -1
}

最佳答案

你可以做一个插入排序。每次添加新记录时,您都会扫描列表以查看它所属的位置并将其插入到那里。这可以与您扫描重复项相结合。

Person *add(Person *head, char *n, int a) {
  char empty[1] = "";
  Person sentinel = {0};
  sentinel.name = empty;
  sentinel.next = head;
  Person *p = &sentinel;
  while (p) {
    int cmp = p->next ? strcmp(n, p->next->name) : -1;
    if (cmp == 0) {
      printf("Name Already Exists in List! Please retry with another name..\n");
      break;
    }
    if (cmp < 0) {
      Person *newNode = malloc( sizeof(Person) );
      newNode->name = malloc( strlen(n) + 1 );
      strcpy(newNode->name, n);
      newNode->age = a;
      newNode->next = p->next;
      p->next = newNode;
      break;
    }
    p = p->next;
  }
  return sentinel.next;  // a possibly-updated copy of head
}

插入排序总是将新元素与下一个 元素(而不是与当前元素)进行比较。这使得处理第一个元素很尴尬,尤其是在列表中。我们通过假装就在列表头部之前的临时“哨兵”来解决这个问题。

还有其他方法。您可以在列表的头部创建新节点,然后将其向下滑动直到就位。如果遇到重复项,则删除新的并修补列表。其他数据结构中的插入排序通常从尾部向头部工作,但这不适用于单链表。

关于c - 我怎样才能按字母顺序排列这个链表?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49804476/

相关文章:

c - 如何在共享内存c中的struct内部分配链表

c - 递归地反向链接列表

algorithm - 使用 3 个数组的双向链表

c++ - 如何分析对函数的每次调用?

c - 我不知道它是如何工作的?

在 C 中从 uint8_t * 转换为 char *

c - 使用 malloc、struct 和 char * 的堆损坏

c - 使用指针在单链表中反向打印

在 C 中创建带有链表的多项式

c - 在C中通过标记读取字符串标记