🚀 更多关于 Windows Internals、调试、逆向和出海相关内容请访问我的个人博客: FrendGuo's Blog

常见算法之排序算法(一)---冒泡排序

排序看起来是个很简单的问题,其实[并不简单]。。。

以下便来聊聊常见的排序算法:

1.冒泡排序(Bubble sort)

冒泡排序是个非常简单的算法,简单的来说,就是依次比较,找出最大值(最小值),然后移动最右端(左端),再用相同的道理找出第二大的,第三大的...依次放到第二、第三个位置(从右往左数)。详细的描述参看维基百科(英文版,中文需 FQ ) 》》》

参考代码:

1
2
3
4
5
6
7
8
9
10
11
void bubble_sort(int* arr, int size)
{
    for (int i = 0; i < size; ++i)
        for (int j = 0; j < size - 1 - i; ++j)
            if (arr[j] > arr[j + 1])
            {
                int tmp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = arr[j];
            }
}

也可以使用以下助记码来帮助记忆:

1
2
3
i∈[0,N-1)               //循环N-1遍
   j∈[0,N-1-i)           //每遍循环要处理的无序部分
     swap(j,j+1)          //两两排序(升序/降序)

最后再来分析下冒泡排序的复杂度:

  • 最优时间复杂度:当序列已经处于排序状态时,时间复杂度最优。此时,时间复杂度时O(n^2). 但这里维基百科上写的时O(n) 啊,为什么呢?实质上,要想实现最优O(n)的冒泡排序啊,必须得对上面的代码做点小的优化,比如加个标志位啊!于是就有下面的代码:
  • 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    void bubble_sort(int* arr, int size)
    {
        bool isComplate = true;
        for (int i = 0; i < size; ++i, isComplate = true)
            for (int j = 0; j < size - 1 - i; ++j)
                if (arr[j] > arr[j + 1])
                {
                    isComplate = false;
                    int tmp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = arr[j];
                }
    }
  • 最坏时间复杂度:很显然,最坏的情况也只能是O(n^2)。
  • 平均时间复杂度:O(n^2)
  • 空间复杂度:指的额外耗费的空间,这里也很明显耗费的空间只是一个常量值(在这里,也就是不随 size 的大小而改变),也就是O(1)

优化:

 这里介绍下冒泡的简单变形:鸡尾酒排序(cocktail_sort),根据上面的冒泡排序,我们每次循环都是一个方向的,那么很自然的想到,我们每次可不可两个方向来比较呢?于是就有了鸡尾酒排序。排序过程如下:

写出代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
template<typename T>
void cocktail_sort(T* arr, int n)
{
    int start = 0;
    int end = n - 1;
 
    while (start < end)
    {
        for (long i = start; i < end; ++i)
        {
            if (arr[i] > arr[i + 1])
            {
                T t = arr[i];
                arr[i] = arr[i + 1];
                arr[i + 1] = t;
            }
        }
        --end;
 
        for (long i = end; i > start; --i)
        {
            if (arr[i] < arr[i - 1])
            {
                int t = arr[i];
                arr[i] = arr[i - 1];
                arr[i - 1] = t;
            }
        }
        ++start;
    }
}

算法复杂度跟冒泡排序也是一样一样的。总的来说性能还是有些许提升的。下面是我用冒泡和鸡尾酒排序来排序100,000个随机数的结果(VS2017):

可以看出效果也的确不是很显著。

Happy Coding!o(* ̄▽ ̄*)o

posted @   frendguo  阅读(118)  评论(0编辑  收藏  举报
编辑推荐:
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示