数据结构与算法之冒泡排序
冒泡排序是一种简单直观的排序算法,其原理是反复交换相邻两个元素,直到没有需要交换的元素为止。具体步骤如下:
从数组的第一个元素开始,依次比较每个元素和它的下一个元素,如果当前元素大于下一个元素,则交换这两个元素的位置。
经过第一轮的比较,数组的最后一个元素已经排好序了。接下来,再次从数组的第一个元素开始比较,直到倒数第二个元素,这样第二轮的比较就可以将倒数第二个元素也排好序了。
进行n-1轮比较,每轮比较都会将当前未排序部分的最大值“冒泡”到已排序部分的末尾。
可以发现,每轮比较都会将当前未排序部分的最大值“冒泡”到已排序部分的末尾,因此称之为冒泡排序。时间复杂度为O(n^2)。尽管它的时间复杂度较高,但是由于其简单易懂,因此在小规模数据的排序中仍然有一定的应用价值。
一、C语言之数据结构与算法之冒泡排序源码实现及详解
冒泡排序是一种简单的排序算法,它的基本思想是通过相邻元素之间的比较和交换来进行排序。该算法在每一轮中比较相邻的两个元素,如果它们的顺序错误,就交换它们的位置。经过若干轮的比较和交换,最终将得到一个有序的序列。下面是 C 语言中实现冒泡排序的源码及详解。
冒泡排序的实现
在 C 语言中,实现冒泡排序可以采用两种方式:一种是使用嵌套循环实现,另一种是使用递归实现。
基于循环的实现
下面是使用嵌套循环实现冒泡排序的代码:
void bubble_sort(int arr[], int size)
{
int i, j, tmp;
for (i = 0; i < size - 1; i++) { // 外层循环控制排序轮数
for (j = 0; j < size - i - 1; j++) { // 内层循环控制比较次数
if (arr[j] > arr[j+1]) { // 如果前一个元素比后一个元素大,则交换它们的位置
tmp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = tmp;
}
}
}
}
该函数接收一个整型数组 arr
和它的大小 size
,并使用冒泡排序算法对数组元素进行排序。具体实现方式如下:
- 外层循环使用变量
i
控制排序轮数,从第一轮开始遍历到倒数第二轮(即size-2
)。 - 内层循环使用变量
j
控制比较次数,每次比较相邻的两个元素,如果它们的顺序错误,就交换它们的位置。 - 每轮比较结束后,最大的元素都会被交换到最后的位置,因此下一轮的比较次数可以减少一次。
- 经过
size-1
轮比较和交换后,数组元素将会被排成有序的序列。
基于递归的实现
下面是使用递归实现冒泡排序的代码:
void bubble_sort_recursive(int arr[], int size)
{
if (size == 1)
return;
int i, tmp;
for (i = 0; i < size - 1; i++) {
if (arr[i] > arr[i+1]) {
tmp = arr[i];
arr[i] = arr[i+1];
arr[i+1] = tmp;
}
}
bubble_sort_recursive(arr, size-1);
}
该函数接收一个整型数组 arr
和它的大小 size
,并使用递归实现冒泡排序算法对数组元素进行排序。具体实现方式如下:
- 如果数组大小为 1,则返回。
- 内层循环同样用于比较和交换相邻元素,每次比较前 i 个元素并交换顺序。
- 递归调用
bubble_sort_recursive
函数,并将数组大小减一,直到数组大小为 1。
冒泡排序的时间复杂度
冒泡排序算法的时间复杂度为 O ( n 2 ) O(n^2) O(n2)。它的内部循环会执行 n − 1 n-1 n−1, n − 2 n-2 n−2, …, 1 1 1 次,因此总比较次数为
∑ i = 1 n − 1 i = n ( n − 1 ) 2 \sum_{i=1}^{n-1}i = \frac{n(n-1)}{2} i=1∑n−1i=2n(n−1)
因此,冒泡排序算法的时间复杂度为 O ( n 2 ) O(n^2) O(n2),其中 n n n 是待排序数组的大小。虽然该算法的时间复杂度较高,但是它的实现简单,适用于小规模的数据集合。
二、C++语言之数据结构与算法之冒泡排序源码实现及详解
冒泡排序是一种简单的排序算法,其基本思想是通过多次比较和交换,每次将最大(或最小)的元素“浮”到数组的最后面。该算法的时间复杂度为O(n^2),不适合处理较大的数据集。
以下是C++语言实现冒泡排序的源码及详解:
#include <iostream>
#include <vector>
using namespace std;
void bubbleSort(vector<int>& nums) {
int n = nums.size();
for (int i = 0; i < n-1; i++) { // 外层循环控制排序轮数
bool flag = false; // 标志位,用于优化
for (int j = 0; j < n-1-i; j++) { // 内层循环控制每轮排序的次数
if (nums[j] > nums[j+1]) { // 如果当前元素比后一个元素大,交换两个元素的位置
swap(nums[j], nums[j+1]);
flag = true; // 标志位置为true
}
}
if (!flag) break; // 如果一轮排序中未发生交换,说明已经有序,直接退出循环
}
}
int main() {
vector<int> nums = {6, 3, 8, 2, 9, 1};
bubbleSort(nums);
for (int num : nums) {
cout << num << " ";
}
return 0;
}
在主函数中,我们定义了一个vector类型的nums,并对其进行了初始化。然后,调用bubbleSort函数对nums进行排序,并输出排序结果。
在bubbleSort函数中,我们使用了两层for循环来实现冒泡排序。外层循环控制排序轮数,内层循环控制每轮排序的次数。
每一轮排序过程中,我们从数组第一个元素开始,依次比较相邻两个元素的大小。如果当前元素比后一个元素大,就将它们互换位置。这样一轮比较下来,最大的元素就会“浮”到数组的最后面。然后,我们在进行下一轮排序时,只需要对前面n-1个元素再次执行类似的操作即可。
为了提高冒泡排序的效率,我们还加入了一个标志位flag。如果在一轮排序中未发生任何交换,说明已经有序,此时就可以直接退出循环。这样可以避免不必要的比较操作,提高算法的效率。
综上所述,冒泡排序是一种简单而常用的排序算法,其实现原理并不复杂。但由于其时间复杂度较高,不适用于大规模数据集的排序。在实际应用中,我们通常会选择更快速和高效的排序算法,如快速排序、归并排序等。
三、java语言之数据结构与算法之冒泡排序源码实现及详解
冒泡排序是一种简单的排序算法,它的基本思想是通过不断比较相邻的元素,将较大的元素交换到后面,较小的元素交换到前面,直到排序完成。下面是Java语言实现冒泡排序的源码及详解:
public class BubbleSort {
public static void bubbleSort(int[] arr) {
int n = arr.length;
for (int i = 0; i < n - 1; i++) {
for (int j = 0; j < n - 1 - i; j++) {
if (arr[j] > arr[j + 1]) {
swap(arr, j, j + 1);
}
}
}
}
private static void swap(int[] arr, int i, int j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
public static void main(String[] args) {
int[] arr = {3, 1, 5, 2, 4};
bubbleSort(arr);
for (int i : arr) {
System.out.print(i + " ");
}
}
}
冒泡排序的时间复杂度为O(n^2),因为它需要进行n-1轮比较,每轮比较需要比较n-i-1次。空间复杂度为O(1),因为只需要借助一个临时变量进行交换操作。
以上代码中的bubbleSort方法实现了冒泡排序算法,它通过两层循环来完成,外层循环控制排序次数,内层循环用来遍历数组并进行元素比较。在每次内层循环中,如果前一个元素大于后一个元素,则交换它们的位置,这样较大的元素就会逐渐“浮”到数组末端,较小的元素就会逐渐“沉”到数组前端。
swap方法用于交换数组中两个元素的位置,它使用了一个临时变量temp来实现交换。
以上代码中的main方法用于测试冒泡排序算法的正确性,它创建了一个整型数组并对其进行排序,最后输出排序结果。
因为冒泡排序效率较低,实际开发中很少使用,而更多地是使用其他高效的排序算法,如快速排序、归并排序等。