发现程序员善于用代码表达逻辑,但是不善于通过文字描述逻辑的细节,故特对冒泡排序的细节重新梳理一遍。
如下为冒泡排序动画演示,最终获得从左至右,从小到大依次排列的数字。
特点:(假设共有N个数字,要求左至右,从小到大进行排序)
1.第1轮比较:
从第一个数开始,与第二数进行大小比较,如果比第二个数字大,则两者调换顺序,否则位置不变;接着第二个数与第三个数进行比较,如果比第三个数字大,则两者调换顺序,否则位置不变;接着第三个数字与第四个数字......,以此类推,直至第N-1个数字与第N个数字进行比较。
注意是相邻位置元素的比较,此轮共进行了N-1次比较大小,并且整个数列所有元素都至少参与了一次大小比较运算,至多参与了N-1次大小比较运算。通过此轮比较获得了整个数列的最大元素,且至于数列的最右侧。
2.第2轮比较:
从第一个元素开始,与第三个元素进行比较,如果比第三个数字大,则两者调换顺序,否则位置不变;接着第三个数字与第四个数字......,以此类推,直至第N-2个数字与第N-1个数字进行比较。(为什么不是直至第N-1个数字与第N个数字进行比较呢?因为在第1轮比较中,第N-1个数字与第N个数字已经进行大小比较了,此时显然第N个数比第N-1个数字最大,无需比较了)
此轮共进行了N-2次比较,除了最右侧最大的那个预算以外的所有元素都至少参与了一次大小比较运算,至多参与了N-1次大小比较运算。通过此轮比较获得了整个数列的倒数最2元素,且至于数列的右侧倒数第2的位置。
。。。。。
第N-1轮比较(举例来说,3个数字组成的数组,经过2轮冒泡排序的比较就可以获得从左至右,从小到大的数组)
此轮共进行了1次比较,除了最右侧最大的那个预算以外的所有元素都至少参与了一次大小比较运算,至多参与了N-1次大小比较运算。通过此轮比较获得了整个数列的倒数最N-1个元素,且至于数列的右侧倒数第N-1的位置。
总结:对N个数进行排序,经过了N-1轮比较。每轮比较中都是从左至右方向,相邻进行比较的。每次都是从第1个位置的数字开始进行比较,第1轮比较的次数最多,从左到最右的位置每个数字都参与了比较,动静最大,最后一轮只有1次比较,只局限在最左侧的两个数字,动静最小。
共进行了 (N-1)+(N-2)+(N-3)+.......3+2+1=(N-1)N/2次比较,即时间复杂度为o()
public class MaoPao {
public static void main(String[] args) {
int[] ints = {8 , 4 , 3 , 1 , 5 , 12 , 72 , 23 , 13 , 0 , 2};
int length = ints.length;
//共进行了length - 1轮比较
for (int i = 0; i < length - 1; i++) {
//当前轮比较的次数为(length - i - 1)次,比较的次数随着轮次的增加越来越少,是从左至右相邻进行比较
//每轮都是从第1个位置开始进行比较,假如进入了第N轮比较,则可以获得倒数第N大的数字,并位于右往左,倒数第N个位置
for (int j = 0; j < length - i - 1; j++) {
if (ints[j + 1] < ints[j]) {
int temp = ints[j + 1];
ints[j + 1] = ints[j];
ints[j] = temp;
}
}
}
for (int a:ints
) {
System.out.println(a);
}
}
}