C++实现冒泡排序的多种方式详解

 更新时间:2025年10月13日 09:37:02   作者:无限进步_  
冒泡排序是最基础的排序算法之一,它的核心思想是通过相邻元素的比较和交换,将较大的元素逐步冒泡到数组的末尾,今天我们来分析三种不同的冒泡排序实现方式,每种都有其独特之处,需要的朋友可以参考下

引言

冒泡排序是最基础的排序算法之一,它的核心思想是通过相邻元素的比较和交换,将较大的元素逐步"冒泡"到数组的末尾。今天我们来分析三种不同的冒泡排序实现方式,每种都有其独特之处。

算法基础

冒泡排序的基本原理很简单:重复遍历待排序的数列,一次比较两个元素,如果它们的顺序错误就把它们交换过来。遍历数列的工作重复进行,直到没有再需要交换的元素,这意味着该数列已经排序完成。

时间复杂度:

  • 最坏情况:O(n²)
  • 最好情况:O(n) - 优化后
  • 平均情况:O(n²)

空间复杂度:O(1)

方法一:基础冒泡排序

int main()
{
    int a[] = { 2,1,5,7,3,9,0,4,6,8 };
    int temp = 0;
    int n = sizeof(a) / sizeof(a[0]);
    printf("%d\n",n);
    
    for (int i = 0; i < n-1; i++)
    {
        for (int j = 0; j < n - 1 - i; j++)
        {
            if ( a[j] > a[j+1] )
            {
                temp = a[j];
                a[j] = a[j + 1];
                a[j + 1] = temp;
            }
        }
    }
 
    for (int k = 0; k < n; k++)
    {
        printf("%d ", a[k]);
    }
    printf("\n");
    return 0;
}

代码解析

  • 数组初始化int a[] = { 2,1,5,7,3,9,0,4,6,8 }; 创建待排序数组
  • 计算数组长度int n = sizeof(a) / sizeof(a[0]); 通过总字节数除以单个元素字节数得到元素个数
  • 双重循环结构
    • 外层循环控制排序轮数:for (int i = 0; i < n-1; i++)
    • 内层循环进行相邻元素比较:for (int j = 0; j < n - 1 - i; j++)
  • 元素交换:使用临时变量temp完成两个元素的交换

特点分析

优点

  • 代码简洁明了,易于理解
  • 逻辑清晰,是学习排序算法的入门首选

缺点

  • 没有优化,即使数组已经有序也会继续执行完整排序过程
  • 效率较低,无法提前结束

方法二:优化版冒泡排序

int main()
{
    int a[] = { 2,1,5,7,3,9,0,4,6,8 };
    int temp = 0, falg = 0;
    int n = sizeof(a) / sizeof(a[0]);
    printf("%d\n", n);
    
    for (int i = 0; i < n - 1; i++)
    {
        int flag = 1; // 假设这趟已经有序了
        for (int j = 0; j < n - 1 - i; j++)
        {
            if (a[j] > a[j + 1])
            {
                flag = 0; // 发生交换就说明,无序
                temp = a[j];
                a[j] = a[j + 1];
                a[j + 1] = temp;
            }
        }
        if (flag == 1) // 这一趟没交换就说明已经有序了,后续无需排序了
        {
            break;
        }
    }
 
    for (int k = 0; k < n; k++)
    {
        printf("%d ", a[k]);
    }
    printf("\n");
    return 0;
}

代码解析

这个版本在基础版本上增加了一个重要的优化:提前终止机制

  • 标志变量int flag = 1; 在每轮排序开始前假设数组已经有序
  • 交换检测:当发生元素交换时,flag = 0; 标记数组仍无序
  • 提前终止:如果一轮排序后flag仍为1,说明没有发生交换,数组已有序,直接退出循环

特点分析

优化效果

  • 对于已经有序或接近有序的数组,效率大幅提升
  • 最好情况下时间复杂度从O(n²)降低到O(n)

实际应用价值

这种优化在实际应用中非常有价值,因为很多场景下数据可能已经部分有序。

方法三:指针版冒泡排序

int main()
{
    int a[] = { 2,1,5,7,3,9,0,4,6,8 };
    int* p = a;
    int temp = 0, falg = 0;
    int n = sizeof(a) / sizeof(a[0]);
    printf("%d\n", n);
    
    for (int i = 0; i < n - 1; i++)
    {
        p = a; // 每趟开始时重置指针到数组开头
        for (int j = 0; j < n - 1 - i; j++)
        {
            if (*p > *(p+1))
            {
                temp = *p;
                *p = *(p + 1);
                *(p + 1) = temp;
            }
            p++; // 指针后移
        }
    }
 
    for (int k = 0; k < n; k++)
    {
        printf("%d ", a[k]);
    }
    printf("\n");
    return 0;
}

代码解析

这个版本使用指针操作代替数组下标,展示了C语言指针的强大功能。

  • 指针初始化int* p = a; 指针p指向数组首地址
  • 指针比较if (*p > *(p+1)) 使用指针解引用比较元素值
  • 指针交换:通过指针直接操作内存完成元素交换
  • 指针移动p++ 使指针指向下一个元素

特点分析

技术特点

  • 展示了指针在数组操作中的应用
  • 代码执行效率可能略有提升(依赖编译器优化)
  • 更接近底层内存操作

学习价值

对于理解C语言指针和内存管理很有帮助,是进阶学习的良好示例。

补充(指针版冒泡排序)

int main()
{
    int a[] = { 2,1,5,7,3,9,0,4,6,8 };
    int* p = a;
    int temp = 0, falg = 0;  // 注意:这里有个拼写错误,应该是flag
    int n = sizeof(a) / sizeof(a[0]);
    printf("%d\n", n);
    
    for (int i = 0; i < n - 1; i++)
    {
        int flag = 1;  // 每轮开始前假设数组已有序
        p = a;  // 重置指针到数组开头
        
        for (int j = 0; j < n - 1 - i; j++)
        {
            if (*p > *(p+1))  // 使用指针比较相邻元素
            {
                flag = 0;  // 发生交换,标记为无序
                temp = *p;
                *p = *(p + 1);
                *(p + 1) = temp;
            }
            p++;  // 指针移动到下一个元素
        }
        
        if (flag == 1)  // 如果本轮没有发生交换
        {
            break;  // 提前结束排序
        }
    }
 
    for (int k = 0; k < n; k++)
    {
        printf("%d ", a[k]);
    }
    printf("\n");
    return 0;
}

三种方法对比

特性方法一方法二方法三
代码复杂度简单中等中等
执行效率稳定O(n²)最好O(n)稳定O(n²)
内存使用
适用场景教学演示实际应用指针学习
优化程度无优化提前终止无优化

总结

三种冒泡排序实现各有特色:

  • 方法一最适合算法初学者,代码清晰易懂
  • 方法二在实际开发中最实用,具备智能优化能力
  • 方法三适合想要深入理解指针和内存操作的开发者

虽然冒泡排序在实际应用中效率不高,但作为算法学习的入门课程,它帮助我们理解排序的基本概念和算法优化的重要性。掌握这三种实现方式,能够为学习更复杂的排序算法打下坚实基础。

无论选择哪种实现方式,理解算法背后的思想才是最重要的!

以上就是C++实现冒泡排序的多种方式详解的详细内容,更多关于C++冒泡排序实现的资料请关注脚本之家其它相关文章!

相关文章

  • C++实现LeetCode(147.链表插入排序)

    C++实现LeetCode(147.链表插入排序)

    这篇文章主要介绍了C++实现LeetCode(147.链表插入排序),本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-07-07
  • C++图书管理系统程序源代码

    C++图书管理系统程序源代码

    这篇文章主要为大家详细介绍了C++图书管理系统程序源代码,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-03-03
  • C语言函数栈帧的创建与销毁详解

    C语言函数栈帧的创建与销毁详解

    函数栈帧(stack frame)就是函数调用过程中在程序的调用栈(call stack)所开辟的空间,下面这篇文章主要给大家介绍了关于C语言函数栈帧的创建与销毁的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2022-09-09
  • 带你粗略了解c++的最大乘积

    带你粗略了解c++的最大乘积

    这篇文章主要为大家详细介绍了C++的最大乘积,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能给你带来帮助
    2021-08-08
  • C语言进阶几分钟带你理解大小端存储模式

    C语言进阶几分钟带你理解大小端存储模式

    这篇文章主要为大家介绍了C语言进阶大小端模式的示例详解,带各位读者朋友五分钟脚踩大小端模式,有需要的朋友可以借鉴参考下,希望能够有所帮助
    2022-02-02
  • C语言结构体计算内存占用问题解析

    C语言结构体计算内存占用问题解析

    这篇文章主要介绍了C语言结构体计算内存占用问题解析,本文通过案例来解析了C语言计算结构体内存的方式和方法,需要的朋友可以参考下
    2021-07-07
  • C语言关于时间复杂度详解

    C语言关于时间复杂度详解

    大家好,本篇文章主要讲的是C语言关于时间复杂度详解,感兴趣的同学赶快来看一看吧,对你有帮助的话记得收藏一下,方便下次浏览
    2022-01-01
  • C++中多才多艺的 const

    C++中多才多艺的 const

    在C++中,关键字const可以用来修饰任何作用域内的变量、函数参数、函数本体、函数返回值、成员函数、迭代器,也可以用来修饰指针本身和指针目标,可谓多才多艺,我们要详细了解其内部细节,以及逻辑奥秘,让这把多功能瑞士军刀尽情发挥其作用,需要的朋友可以参考一下
    2021-09-09
  • C++中Boost.Chrono时间库的使用方法

    C++中Boost.Chrono时间库的使用方法

    chrono是一个time library, 源于boost,现在已经是C++11标准了,下面这篇文章主要给大家介绍了关于C++中Boost.Chrono时间库的使用方法,文中通过示例代码介绍的非常详细,对大家具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧。
    2017-09-09
  • C语言中使用lex统计文本文件字符数

    C语言中使用lex统计文本文件字符数

    这篇文章主要介绍了C语言中使用lex统计文本文件字符数,本文直接给出实现代码,需要的朋友可以参考下
    2015-04-04

最新评论