冒泡排序:
假设一个数组 int[] array 长度为5,坐标为:[0]、[1]、[2]、[3]、[4] ,每相邻两位数比较。
第一次比较:[0]与[1]、[1]与[2]、[2]与[3]、[3]与[4] (array[4] 已是最大)
第二次比较:[0]与[1]、[1]与[2]、[2]与[3]
第三次比较:[0]与[1]、[1]与[2]
第四次比较:[0]与[1](array[0] 已是最小)
1 public class BubbleSort { 2 3 public static void main(String[] args) { 4 5 int[] array = { 1, 65, 48, 9, 5, 2, 33, 6, 45, 88, 11, 2, 59, 4 }; 6 7 int c = -1; 8 //控制次数 9 for (int i = 0; i < array.length - 1; i++) { 10 //内部两两比较 11 for (int j = 0; j < array.length - 1 - i; j++) { 12 if (array[j] > array[j + 1]) { 13 c = array[j]; 14 array[j] = array[j + 1]; 15 array[j + 1] = c; 16 } 17 } 18 } 19 20 for (int r : array) { 21 System.out.println(r); 22 } 23 } 24 25 }
效率:
在一个10个数据项的数组中,第一次排序时要进行 9 次比较,第二次排序进行 8 次比较 。。。。 直到最后一次进行 1 次比较,那么次数为:
9 + 8 + 7 + 6 + 5 + 4 + 3 + 2 + 1 = 45,假设数组的长度为 N , 那么:
(N-1) + (N-2) + (N-3) + (N-4) + ...... + 1 = N * (N-1) / 2 ( 约成 N2 )
假设每次大概只有一半的数据需要交换,那么交换的次数为:N2 / 4
在大O表示法中,忽略了 2 和 4 , 那么意味着比较和交换的次数都为 N2 ,认为冒泡排序需要O(N2) 时间级别。
类似冒泡的一种排序
1 for (int i = 0; i < array.length; i++) { 2 for (int j = i + 1; j < array.length; j++) { 3 if (array[i] > array[j]) { 4 c = array[i]; 5 array[i] = array[j]; 6 array[j] = c; 7 } 8 } 9 }
选择排序:
排序从左开始,记录下最矮数值的坐标,在第一轮之中做了(N-1)次的比较之后,已经记录下最矮数值的坐标,再与其坐标的数值与最左边的数值进行交换。
也就是每一轮的比较,都只做 1 次交换。
1 public class SelectSort { 2 3 public static void main(String[] args) { 4 int[] array = { 1, 65, 48, 9, 5, 2, 33, 6, 45, 88, 11, 2, 59, 4 }; 5 6 int c; 7 int min ; 8 for (int i = 0; i < array.length -1 ; i++) { 9 min = i; 10 for (int j = i + 1; j < array.length; j++) { 11 if (array[j] < array[min]) { 12 min = j; 13 } 14 } 15 c = array[min]; 16 array[min] = array[i]; 17 array[i] = c; 18 } 19 20 for (int r : array) { 21 System.out.println(r); 22 } 23 } 24 25 }
效率:
与冒泡排序执行了相同次数的比较:N * (N-1) / 2,但交换次数只进行不到 N 次,当 N 值很大时,比较次数是主要的,所以结论是选择排序与冒泡排序一样运行了 O(N2)时间,但是选择排序无疑是更快的,因为交换次数少。
插入排序:
局部有序:在冒泡和选择排序中是不会出现的,在这两种算法中,一组数据项在某一时刻是完全有序,在插入排序中,一组数据仅仅是局部有序。
在队伍之中有一个标记的成员,在这个标记成员的左边的所有成员都是局部有序,意味着这一部分成员是按照顺序的(从小到大,标记成员是最大的)。
标记往右移,新的标记成员 temp 与左边一位(局部有序中最大的成员)M 比较,如果temp 比 它小,则 M 放到新标记的位置(原temp的位置),之后temp 再与左边第二位成员比较。。。如此下去,如果找到temp 与比较的值大的话,就放在该比较值右边的位置。
1 public static void insert() { 2 int[] array = { 1, 65, 48, 9, 5, 2, 33, 6, 45, 88, 11, 2, 59, 4 }; 3 int in, out; 4 for (out = 1; out < array.length; out++) { 5 int temp = array[out]; 6 in = out; 7 while (in > 0 && array[in - 1] >= temp) { 8 array[in] = array[in - 1]; 9 in--; 10 } 11 array[in] = temp; 12 } 13 }
插入排序效率:
第一趟排序:最多一次,第二趟:最多两次。。。。。最后一趟,最多N-1次。
1 + 2 + 3 + 4 + ...... + (N-1) = N*(N-1)/2
平均只有一半数据真的进行比较,那么 N*(N-1)/4
插入排序算法仍然需要O(N2)的时间,复制的次数大致等于比较的次数。然而,一次复制(插入)与一次交换(冒泡、选择)的时间耗费不同,所以一般情况下,它要比冒泡排序快一倍,比选择排序还快一些。