冒泡排序是交换排序的一种。
所谓交换,是指根据序列中的两个元素关键字的比较结果来对换这两个记录在序列中的位置。基于交换的排序算法很多,包括冒泡和快排。
算法思想
从后往前(或从前往后)两两比较相邻元素的值,若为逆序,则交换它们,直到序列比较完。我们称它为第一趟冒泡,结果是将最小的元素交换到待排序列的第一个位置(或将最大的元素交换到待排序列的最后一个位置),下一趟冒泡时,前一趟确定的最小元素(或最大元素)不再参与比较,每趟冒泡的结果是把序列中的最小元素(或最大元素)放到了序列的最终位置…因此这样最多需要n-1趟冒泡就能所有元素排好序。
优化
使用布尔标记来记录交换动作的出现,这一修改只是改进了最好情况下的行为。
实现
Python实现:
def swap(lyst:list,i:int,j:int)->None:
tmp = lyst[i]
lyst[i] = lyst[j]
lyst[j] = tmp
def bubbleSort(lyst: list)->list:
n = len(lyst)
while n>1:
flag = False
for i in range(1,n):
if lyst[i] <lyst[i-1]:
swap(lyst,i,i-1)
flag = True
if flag== False: return lyst
n -= 1
return lyst
print(bubbleSort([9,1,2,5,5,4,8,6,3,5]))
print(bubbleSort([2,3,5,6,8]))
C++实现:
#include <iostream>
#include <vector>
using namespace std;
void swap(vector<int>& lyst, int i,int j){
int tmp = lyst[i];
lyst[i] = lyst[j];
lyst[j] = tmp;
}
vector<int> bubbleSort(vector<int>& lyst){
int n = lyst.size();
while(n>1){
bool flag = false;
for (int i =1;i<n;i++){
if(lyst[i-1]>lyst[i]) {
swap(lyst,i,i-1);
flag = true;
}
}
if(flag==false) return lyst;
n--;
}
return lyst;
}
int main() {
vector<int> test = {1,2,3,4};
vector<int> res = bubbleSort(test);
for (int i = 0; i < res.size(); i++){
cout << res[i] << " ";
}
return 0;
}
算法分析
时间: 当初始序列有序时,第一趟冒泡后flag依然为false(本趟冒泡没有元素交换),从而直接跳出循环,比较次数为n-1,移动次数为0,所以最好情况下的时间复杂度为o(n)。
当初始序列逆序时,需要进行n-1趟排序,第i趟排序需要进行
n
−
i
n-i
n−i次关键字的比较,而且每次都必须移动3次进行交换元素位置,所以,比较次数为
∑
i
=
1
n
−
1
(
n
−
i
)
=
n
(
n
−
1
)
2
\sum^{n-1}_{i=1}(n-i)=\frac{n(n-1)}{2}
∑i=1n−1(n−i)=2n(n−1),移动次数为
∑
i
=
1
n
−
1
3
(
n
−
i
)
=
3
n
(
n
−
1
)
2
\sum^{n-1}_{i=1}3(n-i)=\frac{3n(n-1)}{2}
∑i=1n−13(n−i)=23n(n−1)。时间复杂度为o(
n
2
n^2
n2)。
空间: 仅使用了常数个辅助单元,因而空间复杂度为o(1)。
稳定性: 由于i>j,且L(i)=L(j)时,不会发生交换,因而稳定。