简单.
运行十分缓慢,效率低.
点击此处,演示执行流程
比较相邻两个队员. 如果左边高于右边, 交换位置, 否则不变. 一圈比较下来最高的跑到了最后面; 第二圈忽略最后面的那个数(因为它已经是最大的了), 再从左边开始比较相邻两个数…如此循环
public void testBubbleSort(){
int[] arr = {33,44,22,11,55};
// 外圈循环一次, 最大的"冒泡"到最后边
for(int i=0; i<arr.length-1; i++){
// 内圈循环是为了比较相邻两个数
for(int j=0; j<arr.length-i-1; j++){
if(arr[j]>arr[j+1]){
// 交换位置
int temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
for(int a : arr){
System.out.print(a+" ");
}
}
假设有10个数, 第一圈比较9次, 第二圈比较8次…总共下来是:9+8+7+6+5+4+3+2+1=45次.
一般来说, 数组中有N个数据项, 第一趟排序中有N-1次比较, 第二趟中有N-2次比较, 以此类推. 这种求和公式如下:
改进冒泡排序, 将必要交换次数从O(N^2)减少到O(N).
比较次数仍然为O(N^2).
点击此处,演示执行流程
把所有队员都扫描一遍, 从中挑出来最矮的一个队员. 让最矮的队员和最左边的队员交换位置.所以最左边的队员就是有序的了.注意:这个算法中有序的队员都排在队列的左边(较小的下标值), 而在冒泡排序中有序的是队列右边的数据.
再次扫描队员时,就从1号位置开始(0号已是最矮), 还是寻找最矮的, 然后和1号位置队员交换. 这个过程一只持续到所有队员都排定.
注意:
挑出来最小的, 并不是记录它的值, 而是记录下来他的索引位置, 然后和最左边的索引进行交换.
public void testSelectSort(){
int[] arr = {33,44,22,11,55};
// 外圈, 为了让左边和最小值进行交换(而寻找最小值是内圈的任务)
for(int i=0; i<arr.length-1; i++){
// 将最左边的索引记录给min
int min = i;
for(int j=i+1; j<arr.length; j++){
// 找出最小
if(arr[j]<arr[min]){
min = j;
}
// 交换位置
int temp = arr[min];
arr[min] = arr[i];
arr[i] = temp;
}
}
for(int each : arr){
System.out.print(each+" ");
}
}
选择排序和冒泡排序进行了相同次数的比较N*(N-1)/2. 对于10个数据项, 需要比较45次.然而, 10个数据项只需要少于10次的交换.
当N值很大时, 比较次数是主要的, 所以结论是选择排序和冒泡排序一样运行了O(N^2)时间. 但是, 无疑是选择排序效率更高, 因为它的实际交换次数少.
平均情况下,速度快于冒泡和选择(完全逆序除外).
较于冒泡和选择稍微复杂.
点击此处,演示执行流程
取出一个(等待被插入)值赋值给一个临时变量, 然后将这个临时变量和它左边的值作比较, 如果左边的值大于这个临时值, 则将左边的值向右移动.否则就将临时值插入到这个位置. 一轮循环到此结束, 接下来再将上一个(等待被插入)的值的下一个值取出来作为新的(等待被插入的值),再次执行上边的步骤.如此循环, 直至全部有序.
举个例子: 就像整理书架上的书籍一样, 以几本有序的为基准, 将它右边的书本一本一本拿出来, 然后将有序的向右推, 将取出的书本插入到有序的合适的位置.(又有点像整理扑克牌一样)
public void testInsertSort(){
int i,j;
for(i=1;i<arr.length;i++){
// 记录下来被取出(等待被插入)的值
int temp = arr[i];
j=i;
// 拿这个被取出的值和它左边的值比较, 如果左边的值大于它,将左边的值向右移动一位
while(j>0&&arr[j-1]>=temp){
arr[j] = arr[j-1];
--j;
}
// 最后将等待被插入的值插入到合适的索引位
arr[j] = temp;
}
for(int each: arr){
System.out.print(each + " ");
}
}