链表与归并排序

一个C#链表实例

链表,主要是"链"每个类中,都包含一个指向后一个节点的指针

csharp 复制代码
class ListNode
    {
        public string Name { get; set; }
        public ListNode Next;

        public ListNode(string name)
        {
            this.Name = name;
            this.Next = null;
        }
    }

基本练成链子,对于插入,仅仅是对应节点的Next赋值,但要注意,保存头结点指针。

csharp 复制代码
 ListNode Head = new ListNode("Mr.Green");
            Head.Next = new ListNode("Mr.Black");
            Head.Next.Next = new ListNode("Mrs. Blue");
            PrintList(Head,"构建的基础链表为:");
            ListNode IHead = new ListNode("Mr.Brown");
            IHead.Next = Head;
            Head = IHead;
            PrintList(Head, "向链表L表头插入一个单元后构建的基础链表为:");
            ListNode list1 = Head;
            while (list1.Next != null)
            {
                list1 = list1.Next;

            }
            list1.Next = new ListNode("Ms.White");
            PrintList(Head, "向链表L表尾插入一个单元后构建的基础链表为:");
            ListNode insertPos = Head;
            while (insertPos.Next != null && insertPos.Next.Name != "Mr.Black")
            {
                insertPos = insertPos.Next;
            }
            insertPos.Next = new ListNode("Dr.Martin");
            PrintList(Head, "向链表L表中Mr.Black前插入一个单元后构建的基础链表为:");

排序算法,冒泡算法这里可以使用,但不推荐,这里使用归并排序,也是本文章记录的核心内容。

排序分为三部分,找终点、拆两半、合并

csharp 复制代码
static ListNode SortList(ListNode head)
    {
        if (head == null || head.Next == null) return head;

        // 当链表只有一个节点时,无需再分割和排序
        if (head.Next == null)
        {
            return head;
        }

        // 获取链表中间节点
        ListNode middle = GetMiddle(head);
        ListNode nextToMiddle = middle.Next;
        middle.Next = null;

        // 分别对左半部分和右半部分链表进行递归排序
        ListNode left = SortList(head);
        ListNode right = SortList(nextToMiddle);

        // 合并两个已排序的子链表
        return Merge(left, right);
    }

    static ListNode GetMiddle(ListNode head)
    {
        if (head == null || head.Next == null)
        {
            return head;
        }

        ListNode slow = head, fast = head;

        // 当链表长度为奇数时,fast会先到达终点,slow会停留在中间节点
        while (fast != null && fast.Next != null && fast.Next.Next != null)
        {
            slow = slow.Next;
            fast = fast.Next.Next;
        }

        return slow;
    }

    static ListNode Merge(ListNode left, ListNode right)
    {
        if (right == null)
        {
            return left;
        }
        if (left == null)
        {
            return right;
        }
        // 根据节点值进行合并,选择较小的节点放在前面
        if (left.Name.CompareTo(right.Name) <= 0)
        {
            // 将左节点链接到左节点的下一个节点与右节点合并的结果
            left.Next = Merge(left.Next, right);

            // 返回当前较小节点作为合并后的新链表的当前节点
            return left;
        }
        else
        {
            // 将右节点链接到左节点与右节点的下一个节点合并的结果
            right.Next = Merge(left, right.Next);

            // 返回当前较小节点(此处可能是右节点)作为合并后的新链表的当前节点
            return right;
        }
    }

其中,找终点算法是一种 快慢找终点,但要注意奇偶问题,否则在递归中会溢出。

相关推荐
海盗12344 小时前
微软技术周报 2026-08-31~09-07:GPT-6 Astra 登陆 Foundry、M365 全球认证故障复盘、C# 15 封闭层级
gpt·microsoft·c#
reasonsummer5 小时前
【办公类-115-01】20260906育儿知识(家园小报)批量制作(2026年9月-2027年6月)
开发语言·数据库·c#
软件黑马王子6 小时前
13.缓存池优化:对象上限配置
开发语言·前端框架·c#
唐青枫6 小时前
C#.NET StructureMap 从依赖注入到项目实战
c#·.net
fujisheng6616 小时前
FUI 编译期装配实践:从反射注册到 Source Generator
c#·unity3d
智码看视界7 小时前
.NET 10 推理大模型TensorSharp 3.3.0 部署实测:纯.NET推理引擎反超llama.cpp 1.5倍,DFlash2提速62%
c#·.net·llama.cpp·.net 10·tensorsharp·本地大模型推理·开源推理引擎
格林威7 小时前
C# 图像异步落盘存储:基于Channel 配合 ArrayPool 实现异步落盘
开发语言·人工智能·数码相机·机器学习·计算机视觉·c#·视觉检测
软件黑马王子7 小时前
11.缓存池优化:窗口布局
开发语言·前端框架·c#
格林威7 小时前
C# 图像使用AVX2指令集:使用OpenCvSharp实现字节图像解压缩速度和map_image算子速度提升
开发语言·图像处理·人工智能·计算机视觉·c#·视觉检测·工业相机