You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Linked List上对字符串按字母顺序实现Insertion Sorting

基于链表的字符串插入排序实现方案(支持多字段排序扩展)

链表实现插入排序比数组开销更低,不需要搬移整块元素,仅修改节点指针即可,核心逻辑和数组插入排序一致,只是操作对象从数组下标替换为链表指针。

核心实现思路

  • 单独维护一个带哑节点(dummy head)的已排序空链表,哑节点的作用是统一头插、中间插入的边界逻辑,不需要单独判断插入位置是否为链表头部
  • 逐一遍历原链表的每个节点,每取出一个待排序节点,先暂存它在原链表的下一个节点,避免修改指针后原链表断链
  • 从已排序链表的头部开始遍历,找到第一个排序值大于当前节点的前驱位置,把当前节点插入到该位置之后
  • 把字符串比较逻辑抽成独立的可传入函数,后续切换按名字、按姓氏排序时,不需要修改排序核心逻辑,只要替换比较函数即可

可直接参考的实现代码

以下是C语言实现,和常规的人员链表节点结构完全适配:

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

// 链表节点结构,对应你已经完成的定义
typedef struct PersonNode {
    char firstName[50];
    char lastName[50];
    struct PersonNode *next;
} PersonNode;

// 定义比较函数规则:返回值<0表示a排在b前,=0表示相等,>0表示b排在a前
typedef int (*CompareFunc)(PersonNode* a, PersonNode* b);

// 按名字(firstName)排序的比较逻辑
int compareByFirstName(PersonNode* a, PersonNode* b) {
    return strcmp(a->firstName, b->firstName);
}

// 后续要实现按姓氏排序只要新增这个比较函数即可,不需要改排序主逻辑
int compareByLastName(PersonNode* a, PersonNode* b) {
    return strcmp(a->lastName, b->lastName);
}

// 链表插入排序主函数,传入原链表头节点和比较函数,返回排序后的链表头
PersonNode* insertionSortList(PersonNode* head, CompareFunc cmp) {
    PersonNode sortedDummy = {.next = NULL}; // 已排序链表的哑节点
    PersonNode* curr = head; // 当前待插入的节点

    while (curr != NULL) {
        // 提前暂存原链表的下一个节点,防止改指针后断链
        PersonNode* nextBackup = curr->next;

        // 遍历已排序链表,找到待插入的前驱位置
        PersonNode* insertPos = &sortedDummy;
        while (insertPos->next != NULL && cmp(insertPos->next, curr) < 0) {
            insertPos = insertPos->next;
        }

        // 完成节点插入
        curr->next = insertPos->next;
        insertPos->next = curr;

        // 处理原链表下一个节点
        curr = nextBackup;
    }

    return sortedDummy.next;
}

常见避坑点

  • 取到当前待插入节点后不要直接遍历找位置,一定要先存好原链表的下一个节点,插入操作会修改当前节点的next指针,不做暂存的话原链表会直接断裂,遍历提前终止
  • 找插入位置时必须从前驱节点开始遍历,不要直接从已排序链表的第一个有效节点开始,否则找到目标位置后拿不到前序节点的指针,没法完成插入
  • 字符串比较必须用语言自带的字符串比较函数(比如C的strcmp、Java的compareTo),直接比较字符串指针/变量本身比的是内存地址,不是字符串字典序,结果完全错误
  • 测试时可以先构造3-5个乱序的名字节点(比如"Zoe", "Alice", "Bob", "Charlie"),排序后遍历打印验证顺序,确认按名字排序没问题后,只要新增按姓氏的比较函数,调用排序函数时传入即可实现切换排序维度的需求。

如果你用其他语言实现,只要把指针操作换成对应语言的引用操作,核心逻辑完全通用。

内容的提问来源于stack exchange,提问作者anon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 14:31:14