我们先看一个案例,一组乱序的数据,现在要把它变成从小到大的一组数据
只有一个原则:相邻数据对换位置
看完以后你就知道什么是冒泡算法了
冒泡算法步骤最全案例
再给冒泡算法归纳总结之前,我们先介绍一个什么叫时间复杂度?
时间复杂度是什么?
我们假设计算机运行一行基础代码需要执行一次运算。
int aFunc(void) {
printf("Hello, World!\n"); // 需要执行 1 次
return 0; // 需要执行 1 次
}
那么上面这个方法需要执行 2 次运算
int aFunc(int n) {
for(int i = 0; i<n; i++) { // 需要执行 (n + 1) 次
printf("Hello, World!\n"); // 需要执行 n 次
}
return 0; // 需要执行 1 次
}
这个方法需要 (n + 1 + n + 1) = 2n + 2 次运算。
我们把 算法需要执行的运算次数 用 输入大小n 的函数 表示,即 T(n) 。
此时为了 估算算法需要的运行时间 和 简化算法分析,我们引入时间复杂度的概念。
定义:存在常数 c 和函数 f(N),使得当 N >= c 时 T(N) <= f(N),表示为 T(n) = O(f(n)) 。
根据如下图来了解定义;
疑问:T(N)是什么?f(N)又代表什么?
T(n)是算法的执行次数函数
f(N)是时间复杂度函数,一般用O(f(N))表示
我们知道常数项对函数的增长速度影响并不大,所以当 T(n) = c,c 为一个常数的时候,我们说这个算法的时间复杂度为 O(1);如果 T(n) 不等于一个常数项时,直接将常数项省略。
案例一、T(n)=2(常量) 算法的时间复杂度为O(1)
int aFunc(void) {
printf("Hello, World!\n"); // 需要执行 1 次
return 0; // 需要执行 1 次
}
案例二、T(n) =2n + 2,此时时间复杂度为 O(n)
int aFunc(int n) {
for(int i = 0; i<n; i++) { // 需要执行 (n + 1) 次
printf("Hello, World!\n"); // 需要执行 n 次
}
return 0; // 需要执行 1 次
}
高次项对于函数的增长速度的影响是最大的。n^3 的增长速度远超 n^2 ,n^2 的增长速度远超 n ,所以我们直接忽略低此项
比如
T(n) = n^3 + n^2 + 29,此时时间复杂度为 O(n^3)。
比如
T(n) = 3n^3,此时时间复杂度为 O(n^3)。
综合起来:如果一个算法的执行次数是 T(n),那么只保留最高次项,同时忽略最高项的系数后得到函数 f(n),此时算法的时间复杂度就是 O(f(n))。为了方便描述,下文称此为 大O推导法。
对于循环体的时间复杂度
1、假设循环体的时间复杂度为 O(n),循环次数为 m,则这个循环的时间复杂度为 O(n×m)。
void aFunc(int n) {
for(int i = 0; i < n; i++) { // 循环次数为 n+1
printf("Hello, World!\n"); // 循环体时间复杂度为 O(1)
}
}
此时时间复杂度为 O((n+1) × 1)=O(n+1),忽略常量,即 O(n)。
2、假设循环体的时间复杂度为 O(n),各个循环的循环次数分别是a, b, c...,则这个循环的时间复杂度为 O(n×a×b×c...)
void aFunc(int n) {
for(int i = 0; i < n; i++) { // 循环次数为 n+1
for(int j = 0; j < n; j++) { // 循环次数为 n+1
printf("Hello, World!\n"); // 循环体时间复杂度为 O(1)
}
}
}
时间复杂度为 O((n+1) × (n+1) × 1)=O(n^2+2*n+1)=O(n^2)
3、总的时间复杂度等于其中最大的时间复杂度
void aFunc(int n) {
// 第一部分时间复杂度为 O(n^2)
for(int i = 0; i < n; i++) {
for(int j = 0; j < n; j++) {
printf("Hello, World!\n");
}
}
// 第二部分时间复杂度为 O(n)
for(int j = 0; j < n; j++) {
printf("Hello, World!\n");
}
}
此时间复杂度为 max(O(n^2), O(n)),即 O(n^2)。
我们现在回到冒泡排序的话题
若一组数据本身就是从小到大有序的,所需的关键字比较次数C=n-1,
为什么明明是有序的,还要比较n-1次?
我总得知道这组数据是不是有序的吧!
记录移动次数M=0;冒泡排序最好时间复杂度为O(n)
若一组数据从大到小的,需要进行n轮排序,每轮进行n-1次比较的;
且每次比较都必须移动记录三次来达到交换记录位置。在这种情况下,比较和移动次数均达到最大值:
冒泡排序最坏时间复杂度为