单链表的冒泡排序实现:从原理到代码详解

单链表的冒泡排序实现:从原理到代码详解

引言

单链表作为一种常见的数据结构,其排序操作因节点无法随机访问(需通过指针遍历)而与数组排序存在差异。冒泡排序因其实现简单、无需额外空间(仅需指针操作),成为单链表排序的常用选择。本文将详细解析单链表冒泡排序的原理、实现细节、优化点及常见错误,帮助读者彻底掌握这一算法。

一、单链表冒泡排序的核心思路

冒泡排序的核心是重复遍历链表,每次比较相邻节点的值,若顺序错误则交换,直至整个链表有序。针对单链表的特点,算法需解决两个关键问题:

  1. 如何标记每趟排序的终点(避免重复比较已排好的尾部元素);
  2. 如何检测链表是否已提前有序(减少无效遍历)。

二、算法关键变量解析

在实现代码中,三个指针变量是核心,需明确其作用:

变量名作用
pPre指向当前比较的前一个节点
pCur指向当前比较的后一个节点(与pPre相邻)
pTail标记每趟排序的终点(初始为NULL,每趟排序后指向当前趟的最后一个节点,下一趟排序仅需遍历到pTail前)

此外,IsChange变量用于标记当前趟是否发生过交换:若未发生交换,说明链表已完全有序,可直接退出排序,避免后续无效操作。

三、代码实现与详细注释

// 单链表冒泡排序函数(升序)
// plist为链表头指针
void BubbleSort(pList plist) {  pNode pCur = NULL;    // 当前节点指针pNode pPre = NULL;    // 当前节点的前一个节点指针pNode pTail = NULL;   // 每趟排序的终点指针(初始为NULL,即链表末尾)// 边界条件:空链表或只有一个节点,无需排序if (plist == NULL || plist->next == NULL) {  return;  }// 外层循环:控制排序趟数(每趟将最大元素"冒泡"到尾部)// 当plist == pTail时,说明所有元素已排序完成while (plist != pTail) {  int IsChange = 0;  // 标记当前趟是否发生交换(0:未交换,1:已交换)pPre = plist;      // 每趟开始时,pPre从链表头出发pCur = pPre->next; // pCur指向pPre的下一个节点// 内层循环:控制每趟的比较次数(遍历到pTail前)while (pCur != pTail) {  // 若前一个节点值大于后一个节点值,交换数据(升序排序)if (pPre->data > pCur->data) {  // 修正原代码的交换错误:正确的交换逻辑int tmp = pPre->data;  pPre->data = pCur->data;  pCur->data = tmp;  IsChange = 1;  // 标记发生交换}// 移动指针,继续比较下一对相邻节点pPre = pPre->next;  pCur = pCur->next;  }// 若当前趟未发生交换,说明链表已完全有序,直接退出if (!IsChange) {  return;  }// 更新pTail为当前趟的最后一个节点(下一趟无需比较到此节点)pTail = pPre;  }
}

四、关键逻辑详解

1. 为什么需要pTail

在数组冒泡排序中,每趟排序后最大元素会 “浮” 到末尾,下一趟可减少一次比较。单链表中,pTail的作用类似:每趟排序后,pTail指向当前趟的最后一个节点(即该趟确定的最大元素),下一趟只需遍历到pTail之前,减少无效比较次数,优化效率。

2. IsChange的作用是什么?

若某趟排序中未发生任何交换(IsChange=0),说明链表已完全有序,可直接退出排序。例如,初始链表为1->2->3->4,第一趟遍历后IsChange=0,算法直接返回,避免后续n-1趟的无效遍历,最佳情况下时间复杂度可优化至 O (n)

五、时间复杂度与空间复杂度

  • 时间复杂度
    • 最坏情况(链表逆序):需n-1趟,每趟比较n-i次,总复杂度为O(n²)
    • 最好情况(链表已有序):仅需 1 趟比较,复杂度为O(n)
  • 空间复杂度:仅使用常数个指针变量(pCurpPrepTail等),复杂度为O(1)

六、示例演示

以初始链表3->1->4->2为例,演示排序过程:

  1. 第一趟排序
    • 初始pTail=NULLpPre=3pCur=1
    • 比较3>1:交换后链表为1->3->4->2IsChange=1
    • 移动指针:pPre=3pCur=4(3<4,不交换);
    • 继续移动:pPre=4pCur=2(4>2,交换后链表为1->3->2->4IsChange=1);
    • 第一趟结束,pTail=4(指向当前最大元素 4)。
  2. 第二趟排序
    • pTail=4,遍历至pCur!=4
    • pPre=1pCur=3(1<3,不交换);
    • pPre=3pCur=2(3>2,交换后链表为1->2->3->4IsChange=1);
    • 第二趟结束,pTail=3
  3. 第三趟排序
    • pTail=3,遍历至pCur!=3
    • pPre=1pCur=2(1<2,不交换);
    • 遍历结束,IsChange=0,算法直接返回。

最终链表为1->2->3->4,排序完成。

七、总结

单链表的冒泡排序通过指针操作实现,核心在于利用pTail减少无效比较、利用IsChange检测提前有序,从而优化效率。需注意指针移动逻辑和数据交换的正确性,避免因细节错误导致排序失败。

该算法实现简单、空间开销小,适合小规模链表排序;若需处理大规模数据,可考虑单链表的快速排序等更高效算法。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/90878.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/90878.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何在 Ubuntu 24.04 或 22.04 上安装和使用 GDebi

APT 是 Ubuntu 上安装需要外部依赖项的 Debian 包的一种方式,但还有另一种选择,即 GDebi。本文将介绍如何在 Ubuntu 24.04 上安装 GDebi,以及如何使用它来安装 .deb 包所需的依赖项。 什么是 GDebi? GDebi 是默认的 .deb 包安装器 DPKG 的轻量级替代品。与 DPKG 不同,GD…

俄罗斯方块游戏开发(面向对象编程)

摘要本设计基于MATLAB面向对象编程技术&#xff0c;开发了一款具备完整游戏逻辑的俄罗斯方块游戏。通过类封装实现游戏核心模块&#xff08;方块管理、游戏板状态、碰撞检测等&#xff09;&#xff0c;采用旋转矩阵实现方块变形&#xff0c;结合MATLAB图形用户界面&#xff08;…

背包DP之多重背包

背包DP之多重背包一、多重背包基础认知1.1 问题定义1.2 核心特征二、基础解法&#xff1a;暴力拆分2.1 核心思路2.2 代码实现2.3 局限性分析三、优化解法&#xff1a;二进制拆分3.1 优化原理3.2 拆分步骤3.3 代码实现3.4 复杂度分析四、二进制拆分过程五、多重背包的变种与应用…

Ansible 变量指南:声明、优先级、作用域与最佳实践(一)

Ansible 变量的声明 前言 全面理解 Ansible 变量是编写高效、可维护 Playbook 的关键。由于最近使用 Ansible 比较多&#xff0c;在变量问题上踩了不少坑&#xff0c;也因此对变量的声明&#xff0c;优先级和作用域有了更深的理解。姑且总结一下&#xff0c;分享给大家&#…

[极客大挑战 2019]FinalSQL--布尔盲注

直接看题可以看到题目给了提示盲注&#xff01;那么接下来就是寻找注入点了&#xff01;那么不能发现注入点就是id了&#xff01;注入类型为数值型注入&#xff01;这里直接尝试盲注。但是这里and被过滤了&&也不行。问了几个师傅说用or&#xff0c;但是空格被过滤了&am…

再谈fpga开发(状态机的应用)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】前面说过&#xff0c;fpga上面最基础的部分是寄存器&#xff0c;而所有寄存器存在每一个clock下&#xff0c;都有被翻转的可能性。至于这些寄存器是…

TCP如何解决网络切换问题

一、传统TCP的网络切换问题核心问题&#xff1a;TCP 连接基于四元组&#xff08;源IP、源端口、目的IP、目的端口&#xff09;&#xff0c;IP 变化导致连接失效二、改进方案与技术演进1. MPTCP&#xff08;多路径TCP&#xff09; - 主流解决方案核心机制&#xff1a;单连接多路…

【Linux】常用命令(一)

【Linux】常用命令 一1. ls1.1 ls -a 显示所有文件及其目录1.2 ls -A 不显示当前目录和父目录1.3 ls -d 显示目录本身&#xff0c;而不是显示其内部内容1.4 ls -i 显示文件的inode属性信息1.4.1 实际用途场景1.5 ls -l 显示文件的详细属性信息1.6 ls -R 递归显示所有子文件1.7 …

Window 部署 coze-stdio(coze 开发平台)

参考链接 https://github.com/coze-dev/coze-studio/wiki/2.-%E5%BF%AB%E9%80%9F%E5%BC%80%E5%A7%8B https://github.com/coze-dev/coze-studio/wiki/3.-%E6%A8%A1%E5%9E%8B%E9%85%8D%E7%BD%AE 环境说明 Docker&#xff1a;28.3.2 系统&#xff1a;Window 11 配置要求 CP…

【Git】Git LFS的使用

一、简介 Git LFS&#xff08;Git Large File Storage&#xff09;是由 GitHub 开发的一款 Git 扩展工具&#xff0c;旨在帮助开发者更高效地管理仓库中的大文件。传统 Git 会将文件的每个版本完整存储在仓库历史中&#xff0c;导致大文件&#xff08;如音频、视频、数据集、二…

不坑盒子:Word里1秒制作“花括号”题目,多音字组词、形近字组词……

1. 30秒看懂它能干啥 用“不坑盒子”插件&#xff0c;在 Word 里输入&#xff1a; 乐,l(快乐),yu(音乐);长,chng(长短),zhǎng(长大)点一下【总分关系】&#xff0c;瞬间出现左边是“乐”右边并列两行拼音括号的花括号结构&#xff1b;再点【并列关系】&#xff0c;又能做出只…

Gateway网关层灰度方案—xx互联网医院系统灰度发布设计与思路详解

通过之前技术的积累&#xff0c;终于开始了本文的编写&#xff0c;如果对灰度、负载均衡、上下文传递、网关不太理解&#xff0c;可以先学习博主的以下博客内容。共勉&#xff1a; 企业级 Java 应用灰度发布设计方案与实践全解析《Spring 中上下文传递的那些事儿》 Part 1&…

学习游戏制作记录(改进投掷剑的行为)7.27

1.实现剑跟随飞行方向旋转修改剑的预制体使剑的朝向对准右x轴Sword_Skill_Contorl脚本&#xff1a;private void Update(){transform.right rb.velocity;//时刻更新位置}2.实现剑插入地面或者敌人修改预制体为触发器Sword_Skill_Contorl脚本&#xff1a;private bool canRotat…

嵌入式软件面试八股文

目录 一、指针函数和函数指针 二、指针的大小 三、sizeof 和 strlen 区别 四、数组指针和指针数组 五、C语言里面内存分配的方式 六、struct结构体和union联合体的区别 八、数组和链表的区别 九、写一个宏这个红返回输入参数比较小的一个 十&#xff0c;使用#include<…

Gradle#Plugin

查看任务来自那个插件 /gradlew tasks --all <taskName>Java Plugin Java Library Plugin

渗透高级-----测试复现(第三次作业)

文章目录测试复现一&#xff0c;环境搭建二&#xff0c;通过VS Code连接cacti三&#xff0c;测试测试复现 一&#xff0c;环境搭建 1&#xff0c;在ubuntu虚拟机上安装MySql数据库&#xff1a; apt-get upgrade # 更新apt-get upgrade apt-get update # 更新apt-ge…

LINUX727 磁盘管理回顾1;配置文件回顾

逻辑卷快照 快照为什么这么小RAID 磁盘阵列 raid 0 raid 1 raid5 raid10raid0 raid1 raid5 raid6 raid10 rank;create raid0 mdadm -c /dev/md0 -l 0 -n 2 /dev/sdb3 /dev/sdb4 raid1 mdadm -c /dev/md1 -l 1 -n 2 /dev/sdb5 /dev/sdb6 raid5 mdadm -c /dev/md5 -l 5 -n 3 -x …

【笔记】Einstein关系式 D = ukBT 的推导与应用研究

文章目录从涨落理论和能量均分定理的数学推导基于平衡统计力学的推导1. 漂移流的来源&#xff1a;Jdrift−μρ∇UJ_{drift} -μρ∇UJdrift​−μρ∇U物理机制粒子流的形成2. 扩散流的来源&#xff1a;Jdiffusion−D∇ρJ_{diffusion} -D∇ρJdiffusion​−D∇ρ3. 热平衡要…

AJAX 原理_第一节_XHR 对象

文章目录1.AJAX原理1.1 初识XML1.2 查询参数1.3 案例-地区查询1.4 案例-注册-设置请求头1.AJAX原理 1.1 初识XML AJAX原理是什么? XMLHttpRequest对象 XHR对象定义: 通过XMLHttpRequest可以在不刷新页面的情况下请求特定URL,获取数据.这允许页面在不影响用户操作的情况下,更…

BeautifulSoup 使用详解与实战示例

BeautifulSoup 是一个用于解析HTML和XML文档的Python库&#xff0c;它能够将复杂的HTML文档转换成一个复杂的树形结构&#xff0c;使得我们可以轻松地查找和提取所需的内容。下面我将详细介绍BeautifulSoup的使用流程&#xff0c;并结合实际示例进行说明。一、安装与基础使用1.…