C语言冒泡排序(附带源码和解析)
冒泡排序是一种简单直观的排序算法,它重复地遍历要排序的数列,一次比较两个元素,如果它们的顺序错误就把它们交换过来。这个过程会一直重复,直到没有再需要交换的元素,也就是说该数列已经排序完成。
这个算法之所以叫"冒泡"排序,是因为越小的元素会经由交换慢慢"浮"到数列的顶端,就如同水中的气泡最终会上浮到水面一样。
冒泡排序的基本原理
冒泡排序的核心思想是通过相邻元素的比较和交换,将最大(或最小)的元素逐步“冒泡”到数列的一端。具体来说,冒泡排序的原理如下:
- 比较相邻的元素。如果第一个比第二个大(升序排列),就交换它们两个。
- 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大的数。
- 针对所有的元素重复以上的步骤,除了最后一个。
- 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
为了更好地理解冒泡排序的过程,我们来看一个具体的例子,假设我们要对数组 [5, 2, 8, 12, 1, 6] 进行升序排序:
初始状态:[5, 2, 8, 12, 1, 6] 第一趟: [2, 5, 8, 1, 6, 12] 第二趟: [2, 5, 1, 6, 8, 12] 第三趟: [2, 1, 5, 6, 8, 12] 第四趟: [1, 2, 5, 6, 8, 12] 第五趟: [1, 2, 5, 6, 8, 12](无交换,排序完成)
在每一趟排序中,我们都会将当前未排序部分的最大元素"冒泡"到数列的末尾。经过 n-1 趟排序后(其中 n 是数组的长度),整个数列就变成了有序状态。
C语言实现冒泡排序
下面是冒泡排序的 C 语言实现代码:
#include <stdio.h> void bubbleSort(int arr[], int n) { int i, j, temp; for (i = 0; i < n-1; i++) { for (j = 0; j < n-i-1; j++) { if (arr[j] > arr[j+1]) { // 交换 arr[j] 和 arr[j+1] temp = arr[j]; arr[j] = arr[j+1]; arr[j+1] = temp; } } } } // 打印数组 void printArray(int arr[], int size) { int i; for (i = 0; i < size; i++) printf("%d ", arr[i]); printf("\n"); } int main() { int arr[] = {64, 34, 25, 12, 22, 11, 90}; int n = sizeof(arr)/sizeof(arr[0]); printf("排序前的数组: \n"); printArray(arr, n); bubbleSort(arr, n); printf("排序后的数组: \n"); printArray(arr, n); return 0; }
运行结果:
排序前的数组: 64 34 25 12 22 11 90 排序后的数组: 11 12 22 25 34 64 90
这段代码中,bubbleSort 函数实现了冒泡排序的核心逻辑。外层循环 i 控制排序的趟数,内层循环 j 负责在每一趟中进行相邻元素的比较和交换。
冒泡排序的时间复杂度和空间复杂度
冒泡排序的时间复杂度在最坏情况下是 O(n^2),其中 n 是数组的长度。这是因为我们需要进行 n-1 趟排序,每趟都要比较 n-1、n-2、...、1 个元素对。最好情况下,如果数组已经是有序的,我们只需要进行 n-1 次比较,不需要任何交换,时间复杂度为 O(n)。
空间复杂度方面,冒泡排序是一个原地排序算法,只需要常数级的额外空间,因此空间复杂度为 O(1)。
冒泡排序的优化
标准的冒泡排序可以通过一些优化来提高效率:
- 如果在某一趟排序中没有发生任何交换,说明数列已经有序,可以提前结束排序。
- 记录上一次交换发生的位置,下一轮排序只需要扫描到该位置即可。
下面是优化后的冒泡排序代码:
void optimizedBubbleSort(int arr[], int n) { int i, j, temp; int lastExchange = 0; // 记录最后一次交换的位置 int sortBorder = n - 1; // 无序数列的边界,每次比较只需要比到这里 for (i = 0; i < n-1; i++) { int isSorted = 1; // 假设数列已经有序 for (j = 0; j < sortBorder; j++) { if (arr[j] > arr[j+1]) { temp = arr[j]; arr[j] = arr[j+1]; arr[j+1] = temp; isSorted = 0; // 有元素交换,所以不是有序的 lastExchange = j; // 更新最后交换的位置 } } sortBorder = lastExchange; if (isSorted) break; // 如果没有发生交换,说明已经有序,提前退出 } }
这个优化版本的冒泡排序通过记录最后一次交换的位置,减少了不必要的比较,同时如果整个数列已经有序,可以提前结束排序过程,显著提高了算法的效率。
总结
冒泡排序是一种简单直观的排序算法,虽然在大规模数据排序中效率不高,但它对于理解排序算法的基本思想非常有帮助,尤其是初学者。通过不断比较相邻元素并交换它们的位置,最终将最大(或最小)的元素“冒泡”到数列的一端,从而实现整个数列的排序。
你可能还想关注其它九种排序算法:
- C语言快速排序(附带源码和解析)
- C语言选择排序(附带源码和解析)
- C语言插入排序(附带源码和解析)
- C语言希尔排序(附带源码和解析)
- C语言归并排序(附带源码和解析)
- C语言堆排序(附带源码和解析)
- C语言计数排序(附带源码和解析)
- C语言桶排序(附带源码和解析)
- C语言基数排序(附带源码和解析)
声明:《算法系列教程》为本站“54笨鸟”官方原创,由国家机构和地方版权局所签发的权威证书所保护。