算法原理:
从数组中第一个数开始,依次遍历数组中的每一个数,通过相邻比较交换,每一轮循环下来找出剩余未排序数的中的最大数并“冒泡”至数列的顶端。
概括为:反复调用单趟扫描交互
算法实现:
#include "bubble.h"
void bubblesort ( int A[], int len )
{
//int legth = sizeof(A) / sizeof(a[1]);这儿的A是个指针,计算结果为1
for (size_t i = len; i > 0; i--)//等价于while(len--).遍历的个数
{
for (size_t j = 1; j < i; j++)//A[0,i),利用数组的最右端的边界i。其实也可以直接用最右边的边界,但是这样会增加复杂度
{
if (A[j - 1] > A[j])
{
swap(A[j - 1],A[j]);
}
}
}
/*
当我开始学的时候,总是想从头开始循环,这个时候第二个循环的判断天骄就是
j < len -i.即i表示遍历的次数,也是已经排好的个数。所以len -i 就是第二个
循环需要遍历的次数上界.
这儿 有一个需要注意的边界。如果循环是[0,n),那么j的上界是len - (i + 1)
for (size_t i = 0; i < len; i++)
{
for (size_t j = 0; j < len - (i + 1); j++)
{
if (A[j] > A[j + 1])
{
swap(A[j], A[j + 1]);
}
}
}
或者
for (size_t i = 1; i < len + 1; i++)
{
for (size_t j = 0; j < len - i; j++)
{
if (A[j] > A[j + 1])
{
swap(A[j], A[j + 1]);
}
}
}
*/
}
/******************************************************************************************
* Data Structures in C++
* Auther : luxiang
* github:https://github.com/Lxxing?tab=repositories
* 欢迎交流指正
******************************************************************************************/
inline void swap(int &a, int &b)
{
int tmp = a;
a = b;
b = tmp;
}
void bubblesort(int A[], int len);
template <typename T>
void bubblesort(T A[], unsigned int len)
{
//这是先把小的数排到前面的方法。跟前面的方法相反
//主要在于,第二个循环,如果是从后面开始遍历
for (unsigned int i = 1; i <= len; i++)
{
for (unsigned int j = len; j > i; j++ )
{
if (A[j - 1] > A[j])
{
swap(A[j - 1], A[j]);
}
}
}
}
算法分析:
算法名称 | 时间复杂度(平均) | 时间复杂度(最坏) | 时间复杂度(最好) | 空间复杂度 | 稳定性 |
---|---|---|---|---|---|
冒泡 | O(![]() | O(![]() | O(![]() | 0(1) | 稳定 |
算法时间复杂度:
n + (n-1) + (n-2) + ...+2+1
算法优化:
问题,再遍历的过程中,如果数组已经拍好序,程序还是要继续运行,所以优化思路就是如果数组没有逆序对就退出。
template <typename T>
void bubblesortA(T A[], unsigned int len)
{
bool sorted = false; //整体排序标志位,false表示尚未排序
while (!sorted) { //在尚未确认已全局排序之前,逐趟进行扫描交换
sorted = true; //假定已经排序
for (int i = 1; i < n; i++) { //自左向右逐对检查当前范围A[0, n)内的各相邻元素
if (A[i - 1] > A[i]) { //一旦A[i - 1]与A[i]逆序,则交换
swap(A[i - 1], A[i]);
sorted = false; //设置未排序标志位
}
}
n--; //就位一个元素
}
}