1 冒泡排序

背景

冒泡排序(Bubble Sort),是一种计算机科学领域的较简单的排序算法。
它重复地走访过要排序的元素列,依次比较两个相邻的元素,如果顺序(如从大到小、首字母从Z到A)错误就把他们交换过来。走访元素的工作是重复地进行,直到没有相邻元素需要交换,也就是说该元素列已经排序完成。
这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端(升序或降序排列),就如同碳酸饮料中二氧化碳的气泡最终会上浮到顶端一样,故名“冒泡排序”(来自百度百科doge)。

算法思想

按照惯例,我们首先从一个生活中的实例开始。假设你现在正在上体育课,体育老师让大家按照身高从高到矮排成一排准备做拉伸运动,大部分同学都找到了自己的位置,但是有少部分和旁边的个子差不多高,从他们自身的角度很难看出谁高谁低,这个时候他们就请求了老师的帮助。老师看了看之后,让其中一位同学往右边(个子更高的一边)挪了一位,对比了一下发现还是比较高,于是就又移了一位,最终帮助这位同学找到了合适的位置。老师在帮助这位同学找位置的过程中其实就使用了冒泡排序的思想。
冒泡排序的思想很简单,用伪代码的形式描述如下:

for i = 1..A.length
  for j = 1..A.length
    tmp = A[j]
    if arr[j] > arr[j+1]
      exchange arr[j] with arr[j+1]

下面用一副图向大家展示一下算法思想

我们选取的例子元素很少,但是事实上还是经历了数组的size趟冒泡,即4次,每次会让最大的元素冒到相应的位置,下面展示了源代码,不过这里的版本是经过改进的冒泡排序:如果数组一开始就有序,直接退出不用继续排序。

#include <stdio.h>


/** void swap(int *a, int *b) -> none
 * 冒泡排序辅助交换函数,用于交换数组中的两个元素
 * @params
 * @param a:  需要交换的第一个元素的地址
 * @param b:  需要交换的第二个元素的地址
 * @return:   none
 */
void swap(int *a, int *b) {
	int tmp = *a;
	*a = *b;
	*b = tmp;
}


/** void BubbleSort(int *arr, int size) -> none
 * 冒泡排序
 * @params
 * @param arr:   需要排序的数组 
 * @param size:  数组的大小
 * @return:      none
 */
void BubbleSort(int *arr, int size) {
	for (int i = 0; i < size - 1; i++) {
        int flag = 0;
		for (int j = 0; j < size - 1; j++) {
			if (arr[j] > arr[j+1]) {
				swap(&arr[j], &arr[j+1]);
                flag = 1;
			}
		}
        if(!flag) {
            return ;
        }
	}
}

int main() {
    int arr[] = {6, 10, 13, 5, 8, 3, 2, 11};
    int len = sizeof(arr) / sizeof(arr[0]);
    BubbleSort(arr, len);
    for (int i = 0; i < len; i++)
    {
        printf("%d ", arr[i]);
    }
    printf("\n");
	return 0;
}

算法分析

时间复杂度

最坏的情况是数组是刚好逆序的,那么冒泡排序一共要进行 n − 1 n-1 n1次循环,而每次循环又要进行 n − 1 n-1 n1次交换,因此这个时候一共的比较次数是: ∑ i = 1 n − 1 ( n − i ) = n ( n − 1 ) 2 \sum_{i=1}^{n-1}(n-i) = \frac{n(n-1)}{2} i=1n1(ni)=2n(n1),时间复杂度为 O ( n 2 ) O(n^2) O(n2)
最好的情况是数组刚好是有序的,那么就只用进行一次冒泡,时间复杂度为 O ( n ) O(n) O(n)

空间复杂度

显然我们仅仅使用了一个 f l a g flag flag标志变量,并未额外开辟空间用来存储,因此冒泡排序的空间复杂度为 O ( 1 ) O(1) O(1)

算法稳定性

可以看到在判断的时候我们并未考虑元素相等的情况,因此也就不会交换数值相同元素的位置,所以冒泡排序是稳定的算法

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
冒泡排序是一种简单直观的排序算法,其基本思想是通过相邻元素之间的比较和交换,将最大的元素逐渐移动到最后的位置。 具体而言,冒泡排序的过程如下: 1. 首先,我们从序列的第一个元素开始,比较其与后续的元素大小; 2. 若第一个元素大于后续元素,则交换两者的位置; 3. 依次比较第二个元素和第三个元素,直到序列的倒数第二个元素; 4. 经过第一轮的比较,最大的元素已经移到了最后的位置; 5. 接下来,我们继续进行第二轮的比较,此时我们只需要比较序列中前n-1个元素,因为最后一个元素已经是最大的; 6. 经过n-1轮的比较和交换,最终序列就按照从小到大的顺序排列好了。 冒泡排序的时间复杂度为O(n^2),其中n为序列的长度。这是因为冒泡排序的每一轮都需要比较n-1次,并且总共需要执行n-1轮。 尽管冒泡排序的时间复杂度较高,但它的实现非常简单,且空间复杂度较低,只需要一个额外的存储空间来交换元素的位置。因此,在一些元素个数较少或者序列基本有序的情况下,冒泡排序仍然是一个不错的选择。 值得注意的是,冒泡排序是一种稳定的排序算法,即相等的元素在排序后的相对位置不会改变。这一点对一些特定需求的排序问题可能是非常重要的。 总之,冒泡排序是一种简单但效率不高的排序算法,适用于一些小规模且简单的排序问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值