如何在C语言链表中按姓名字母顺序插入Person节点?
按姓名字母顺序插入链表节点的实现方案
下面是修改后的完整代码,替换了原有的尾插逻辑,实现了按姓名字母顺序插入节点,同时处理了新节点需要成为链表头的情况:
#define _CRT_SECURE_NO_WARNINGS #define PAUSE system("pause") #define CLS system ("cls") #define FLUSH myFlush(); #include<stdio.h> #include<stdlib.h> #include<string.h> #include <ctype.h> #include<time.h> //Function Prototypes void displayMenu(); int getChoice(int* option); void myFlush(); Person* createPerson(const char* name, int age, float weight); void insertSorted(LIST* head, Person* newNode); typedef struct personType { char name[100]; int age; float weight; struct personType* next; }Person; typedef Person* LIST; int main() { LIST start = NULL; // 只保留头节点指针即可,无需linkedList变量 int ageTemp = 0, counter; char nameTemp[100], response; float weightTemp; int option; do { getChoice(&option); switch (option) { case 1: do { CLS; printf("\nEnter a name for person : "); scanf("%[^\t\n]", nameTemp); FLUSH; printf("\nEnter the age for %s: ", nameTemp); scanf("%i", &ageTemp); FLUSH; printf("\nEnter the weight for %s: ", nameTemp); scanf("%f", &weightTemp); FLUSH; // 创建新节点并插入有序链表 Person* newNode = createPerson(nameTemp, ageTemp, weightTemp); insertSorted(&start, newNode); printf("\nWould you like to enter another person?"); printf("\nEnter Y/N: "); scanf("%c", &response); FLUSH; } while (response == 'Y' || response == 'y'); CLS; break; case 2: LIST temp = start; CLS; counter = 1; while (temp != NULL) { printf("Person %i: %s\t Age: %2i Weight: %.2f \n", counter, temp->name, temp->age, temp->weight); counter += 1; temp = temp->next; } printf("\n\n"); PAUSE; CLS; break; case 3: printf("Exiting program...\n"); printf("See you next time :)"); break; default: CLS; printf("That was not a valid selection..."); PAUSE; } } while (option != 3); // 释放内存 while (start != NULL) { LIST temp = start; start = start->next; free(temp); } return 0; } // 创建新的Person节点 Person* createPerson(const char* name, int age, float weight) { Person* newNode = (Person*)malloc(sizeof(Person)); strcpy(newNode->name, name); newNode->age = age; newNode->weight = weight; newNode->next = NULL; return newNode; } // 按姓名字母顺序插入节点,支持更新头节点 void insertSorted(LIST* head, Person* newNode) { // 情况1:链表为空,直接作为头节点 if (*head == NULL) { *head = newNode; return; } // 情况2:新节点比头节点的名字更靠前,更新头节点 if (strcmp(newNode->name, (*head)->name) < 0) { newNode->next = *head; *head = newNode; return; } // 情况3:遍历找到插入位置,用prev跟踪前驱节点 LIST current = *head; LIST prev = NULL; while (current != NULL && strcmp(newNode->name, current->name) >= 0) { prev = current; current = current->next; } // 插入到prev和current之间 prev->next = newNode; newNode->next = current; } void myFlush() { while (getchar() != '\n'); } void displayMenu() { CLS; printf("Please select from the following options:\n\n"); printf("1. Add a Record.\n"); printf("2. Display All Records.\n"); printf("3. Quit.\n\n\n"); printf("Please enter a selection: "); } int getChoice(int* option) { displayMenu(); scanf("%i", option); FLUSH; return toupper(*option); }
关键修改说明
新增模块化函数
createPerson:负责创建并初始化新节点,简化主函数逻辑insertSorted:核心的有序插入函数,处理所有插入场景
有序插入逻辑拆解
- 空链表直接插入:如果
head是NULL,新节点就是头节点 - 插入到头部:用
strcmp比较新节点和头节点的名字,若返回值小于0,说明新节点名字更靠前,直接将新节点的next指向原头,再更新head指针 - 插入到中间/尾部:用双指针
current和prev遍历链表,找到第一个比新节点名字大的节点位置,插入到prev之后
- 空链表直接插入:如果
原代码冗余清理
- 移除了
linkedList和count变量,因为有序插入不需要跟踪尾节点或计数 - 修正了
main函数的返回值(原代码未写return 0,不符合C标准) - 优化了
getChoice函数中的scanf参数(&*option简化为option)
- 移除了
字符串比较说明
- 代码中用
strcmp做区分大小写的字母序比较,如果需要忽略大小写,可以替换为strcasecmp(Linux/macOS),或者自己实现忽略大小写的比较函数:int strcasecmp_custom(const char* a, const char* b) { while (*a && *b) { if (toupper(*a) != toupper(*b)) { return toupper(*a) - toupper(*b); } a++; b++; } return *a - *b; }
- 代码中用
内容的提问来源于stack exchange,提问作者Sebastian Santa
相关产品推荐
相关产品推荐

