冒泡排序
1 基本原理
核心思想:冒泡排序是一种典型的 交换排序 ,通过比较相邻元素大小来决定是否交换位置
2 实例说明
如上图所示,以一组数据{20,40,30,10,60,50} 为例,进行冒泡排序的算法演示:
- 第一轮:从数组第一个元素开始,依次比较相邻元素,如:20与40比较,位置不变;40与30比较交换位置。。。。最后,最大元素60位于数组末尾。
- 第二轮:重复上一步操作,将数组中第二大元素50交换至数组倒数第二位。
- 重复上述操作
- 第五轮,比较10与20,位置不变,完成最终排序
3 代码实现
// 冒泡排序(C++)
void swap(int& a, int& b)
{
int tmp = a;
a = b;
b = tmp;
}
void BubbleSort(vector<int> &vi)
{
for (int i = 0; i < vi.size() ; i++)
{
for (int j = 1; j < vi.size() - i; j++)
{
if (vi[j] < vi[j - 1])
{
swap(vi[j], vi[j - 1]);
}
}
}
}
算法改进说明:1,对于是否已经是有序排列进行判断;2,对已经排序好的元素不参与重复的比较。
//冒泡排序的算法优化
void BubbleSort(vector<int> &vi)
{
int lastExchangeIndex=0; //记录最后一次交换的位置
int sortBorder=vi.size()-1; //无序数列的边界,边界后的元素以及排好序,无需比较
for (int i = 0; i < vi.size() ; i++)
{
bool isSorted=true;//默认有序排列
for (int j = 0; j < sortBorder; j++)
{
if (vi[j] < vi[j + 1])
{
swap(vi[j], vi[j + 1]);
isSorted=false;//产生元素交换,不是有序排列
lastExchangeIndex=j; //把无序数列的边界更新为最后一次交换元素的位置
}
}
sortBorder=lastExchangeIndex;
if(isSorted)
{
break;
}
}
}
4 性能分析
- 1 时间复杂度:
(1)顺序排列时,冒泡排序总的比较次数为n-1(比较一轮后就跳出循环),移动次数为0;
(2)逆序排序时,冒泡排序总的比较次数为n(n-1)/2,移动次数为n(n-1)/2次;
(3)当原始序列杂乱无序时,平均时间复杂度为O(n^2)。 - 2 空间复杂度:
冒泡排序排序过程中,Swap函数需要一个临时变量temp进行两两交换,所需要的额外空间为1,因此空间复杂度为O(1)。 - 3 算法稳定性:
冒泡排序在排序过程中,元素两两交换时,相同元素的前后顺序并没有改变,所以冒泡排序是一种稳定排序算法。