C++实现排序算法:冒泡排序

目录

前言

冒泡排序性质

C++代码实现冒泡排序

冒泡图解

第一趟排序

第二趟排序

第三趟排序

排序结果

结语


前言

冒泡排序的基本思想是通过从前往后(从后往前)两两比较,若为逆序(即arri < arri + 1)则交换。整个排序方式像是在水底泡泡往上浮。本文会给出冒泡排序的C++实现,并辅以图形解释冒泡排序的过程。

冒泡排序性质

|------|---------|-------|------|
| 排序 | 时间复杂度 | 空间复杂度 | 是否稳定 |
| 冒泡排序 | O(n^2) | O(1) | 否 |

C++代码实现冒泡排序

冒泡排序C++实现

cpp 复制代码
#include <iostream>
#include <vector>

using namespace std;

void Print(vector<int> &arr)
{
    for (auto v : arr)
    {
        cout << v << ' ';
    }
    cout << endl;
}

int main()
{
    // arr待排序的vector对象。这里以将arr最终调整为升序为例
    vector<int> arr{9, 1, 6, 7, 6};

    for (int i = 0; i < arr.size(); i++)
    {
        // flag 为一个标志, 如果有一趟没有进行数据交换,
        // 则该序列已经为有序序列, 可以提前跳出循环, 完成排序
        bool flag = false;
        for (int j = 0; j < arr.size() - 1 - i; j++)
        {
            if (arr[j] > arr[j + 1])
            {
                // 满足条件 进行元素交换
                std::swap(arr[j], arr[j + 1]);
                // 修改标志位,证明本趟排序中发生过元素交换
                flag = true;
            }
        }
        // 判断这次比较过程中是否进行交换,
        // 如果没有进行交换则待排序序列已经为有序序列。就可以提前跳出循环。
        if (!flag)
        {
            break;
        }
    }
    // 输出排序后的结果。
    Print(arr);
    return 0;
}

运行结果

冒泡图解

|------|---|---|---|---|---|
| 下标 | 0 | 1 | 2 | 3 | 4 |
| 初始序列 | 9 | 1 | 6 | 7 | 6 |

第一趟排序

注意: 这里的一趟以一次完整的内层循环作为一趟,即在本趟排序中 i 值不变。

|-----------|--------|----------|---|---|---|
| 第一趟第一次比较 | i == 0 | | | | |
| | j == 0 | j+1 == 1 | | | |
| | 9 | 1 | 6 | 7 | 6 |
| 当前arrj > arrj+1 进行交换 j++ == 1 ||||||
| 本次比较后交换结果 | 1 | 9 | 6 | 7 | 6 |

|-----------|--------|--------|----------|---|---|
| 第一趟第二次比较 | i == 0 | | | | |
| | | j == 1 | j+1 == 2 | | |
| | 1 | 9 | 6 | 7 | 6 |
| 当前arrj > arrj+1 进行交换 j++ == 2 ||||||
| 本次比较后交换结果 | 1 | 6 | 9 | 7 | 6 |

|-----------|--------|---|--------|----------|---|
| 第一趟第三次比较 | i == 0 | | | | |
| | | | j == 2 | j+1 == 3 | |
| | 1 | 6 | 9 | 7 | 6 |
| 当前arrj > arrj+1 进行交换 j++ == 3 ||||||
| 本次比较后交换结果 | 1 | 6 | 7 | 9 | 6 |

|-----------|--------|---|---|--------|----------|
| 第一趟第四次比较 | i == 0 | | | | |
| | | | | j == 3 | j+1 == 4 |
| | 1 | 6 | 7 | 9 | 6 |
| 当前arrj > arrj+1 进行交换 j++ == 4 ||||||
| 本次比较后交换结果 | 1 | 6 | 7 | 6 | 9 |

|---|---|---|---|---|---|
| 当前 j == 4 不满足进入循环条件 j < arr.size() - 1 - i 跳出内层循环, i++ = 2 进入第二趟排序. ||||||

本趟排序中将 9 这个序列中最大的值,调整到最后一个位置。所以当前只有 前arr.size() - 1 - i个元素处于无序状态。

第二趟排序

|---------|---|---|---|---|---|
| 下标 | 0 | 1 | 2 | 3 | 4 |
| 第二趟初始序列 | 1 | 6 | 7 | 6 | 9 |

|-----------|--------|------------|---|---|---|
| 第一次比较 | | i == 1 | | | |
| | j == 0 | j + 1 == 1 | | | |
| | 1 | 6 | 7 | 6 | 9 |
| 当前arrj < arrj+1 不进行交换 j++ == 1 ||||||
| 本次比较后交换结果 | 1 | 6 | 7 | 6 | 9 |

|-----------|---|--------|----------|---|---|
| 第二次比较 | | i == 1 | | | |
| | | j == 1 | j++ == 2 | | |
| | 1 | 6 | 7 | 6 | 9 |
| 当前arrj < arrj+1 不进行交换 j++ == 2 ||||||
| 本次比较后交换结果 | 1 | 6 | 7 | 6 | 9 |

|-----------|---|--------|--------|----------|---|
| 第三次比较 | | | | | |
| | | i == 1 | | | |
| | | | j == 2 | j++ == 3 | |
| | 1 | 6 | 7 | 6 | 9 |
| 当前arrj > arrj+1 进行交换 j++ == 3 ||||||
| 本次比较后交换结果 | 1 | 6 | 6 | 7 | 9 |

|---|---|---|---|---|---|
| 当前 j == 3 不满足进入循环条件j < arr.size() - 1 - i 跳出内层循环, i++ = 2 进入第三趟排序. ||||||

第三趟排序

|---------|---|---|---|---|---|
| 下标 | 0 | 1 | 2 | 3 | 4 |
| 第三趟初始序列 | 1 | 6 | 6 | 7 | 9 |

|-----------|--------|----------|--------|---|---|
| 第三趟第一次比较 | | | i == 2 | | |
| | j == 0 | j+1 == 1 | | | |
| | 1 | 6 | 6 | 7 | 9 |
| 当前arrj < arrj+1 不进行交换 j++ == 1 ||||||
| 本次比较后交换结果 | 1 | 6 | 6 | 7 | 9 |

|-----------|---|--------|----------|---|---|
| 第三趟第二次比较 | | | i == 2 | | |
| | | j == 1 | j+1 == 2 | | |
| | 1 | 6 | 6 | 7 | 9 |
| 当前arrj == arrj+1 不进行交换 j++ == 2 ||||||
| 本次比较后交换结果 | 1 | 6 | 6 | 7 | 9 |

|---|---|---|---|---|---|
| 当前 j == 2 不满足进入循环条件j < arr.size() - 1 - i 跳出内层循环, 本次排序过程中没有进行一次数据交换(示例代码中的 flag 标志位 没有被改变), 所以该序列,已经是有序序列了. 所以提前跳出循环. 排序成功. ||||||

排序结果

最终排序结果:

|--------|---|---|---|---|---|
| 下标 | 0 | 1 | 2 | 3 | 4 |
| 初始序列 | 9 | 1 | 6 | 7 | 6 |
| 最终排序结果 | 1 | 6 | 6 | 7 | 9 |

根据结果,可以发现初始序列中和最终结果中的 6 和 6 的相对位置并没有发生改变,所以 冒泡排序是稳定 的

结语

希望本文对你有所帮助,谢谢点赞关注收藏。如果有什么问题,欢迎私信或者评论区讨论。

感谢阅读

相关推荐
.道阻且长.1 天前
2.LeetCode算法习题讲解--双指针--复写零
算法·leetcode·职场和发展
To_OC1 天前
LC 438 找到所有字母异位词:暴力超时后,我靠滑动窗口一招搞定
javascript·算法·leetcode
白狐_7981 天前
408数据结构第5章:二叉树遍历序列题——技巧、判断与真题型总结
数据结构
Forever Nore1 天前
学完C语言力扣第一题做不来正常吗
数据结构·算法
hansang_IR1 天前
【题解】LC:倍增 / 区间并查集(Range Parallel Unionfind)
c++·算法·并查集
Tisfy1 天前
LeetCode 3731.找出缺失的元素:哈希 / 排序
算法·leetcode·哈希算法·排序·哈希表
lucas_AI1 天前
Q-CueGraph:你的多模态大模型会 zoom,但真的知道该看哪儿吗?
人工智能·算法
kaixin_啊啊1 天前
test_机器学习算法学习
学习·算法·机器学习
liulilittle1 天前
MOE路由:路由(logits: top-k/8)
c++·人工智能·算法·机器学习·llm