1.基本思想:
从序列的一端开始往另一端冒泡,依次比较相邻的两个数的大小。
设数组长度为N。
1.每轮比较相邻的前后两个数据,如果前面数据大于(或者小于)后面的数据,就将这两个个数据交换。
2.这样每轮对数组的第0个数据到N-1个数据进行一次遍历后,最大或者最小的一个数据就到数组第N-1个位置。
3.第一轮比较到下标为N-1的数据(最后一个),以后每次比较都-1。
2.图解冒泡排序:
以 [ 8,2,5,9,7 ] 这组数字来做示例:
从左往右依次冒泡,将小的往右移动(排降序)
第一轮冒泡:
首先比较第一个数和第二个数的大小,我们发现 2 比 8 要小,那么保持原位,不做改动。位置还是 8,2,5,9,7 。指针往右移动一格,接着比较:
比较第二个数和第三个数的大小,发现 2 比 5 要小,所以位置交换,交换后数组更新为:[ 8,5,2,9,7 ]。
指针再往右移动一格,继续比较:
比较第三个数和第四个数的大小,发现 2 比 9 要小,所以位置交换,交换后数组更新为:[ 8,5,9,2,7 ]。同样,指针再往右移动,继续比较:
比较第 4 个数和第 5 个数的大小,发现 2 比 7 要小,所以位置交换,交换后数组更新为:[ 8,5,9,7,2 ]。
下一步,指针再往右移动,发现已经到底了,则本轮冒泡结束,处于最右边的 2 就是已经排好序的数字。
通过这一轮不断的对比交换,数组中最小的数字移动到了最右边。
重复上述步骤,得到的最终结果是:
3.代码实现冒泡排序如下:
void Swap(int* p1, int* p2)
{
int tmp = *p1;
*p1 = *p2;
*p2 = tmp;
}
void BubbleSort(int* arr, int sz)
{
for (int j = 0; j < sz; j++)
{
//一趟排序
for (int i = 1; i < sz-j; i++)
{
if (arr[i - 1] < arr[i])
{
//前一个比后一个小,就交换
Swap(&arr[i - 1], &arr[i]);
}
}
}
}
4.冒泡排序的小优化:
假设我们要排降序,如果数组此时就是降序,那么在第一轮比较过后数据并没有发生交换,那就不要再进行多于的后续比较了,直接跳出循环即可。
void BubbleSort(int* arr, int sz)
{
for (int j = 0; j < sz; j++)
{
int exchange = 0;//默认是有序的
//一趟排序
for (int i = 1; i < sz-j; i++)
{
if (arr[i - 1] > arr[i])
{
//前一个比后一个大,就交换
Swap(&arr[i - 1], &arr[i]);
//如果不是有序的就发生了交换,exchange=1
exchange = 1;
}
}
//如果一趟比较过后发现是有序的,就直接跳出循环
if (exchange == 0)
{
break;
}
}
}
5.时间复杂度和稳定性的分析
最好:就是顺序时,时间复杂度为O(N)
乱序时:时间复杂度为O(N*N)
所以冒泡排序的时间复杂度是O(N*N)。
冒泡排序算法是稳定的。