认识时间复杂度:
时间复杂度为,在一个算法的流程中,常数操作数量的指标,这个指标叫做O(字母O而非数字零),big O。具体为 ,如果常数操作数量的表达式中,只要高阶项,不要低阶项,也不要高阶项系数,剩下的部分记为f(N),那么该算法的时间复杂度为O(f(N))。
比如:我们求一个数组中的最大值
求数组中的最大值,一般思路是把数组遍历一遍,设置一个中间变量max来记录最大值,中间用来取数组中的数的操作,赋值操作,这些操作成常数操作(所谓常数操作,指的是完成这个操作的时间和数据量无关,它是一个固定的值)。在数组中的寻址代价是big O(1)的,即常数操作,拿到的这个数和max进行比较,比较的这个操作也是常数操作。从0位置遍历到n-1位置,我们花费的总代价为:n*常数操作。即认为完成这些操作的代价为C*n(其中C为常数),我们就说它是big O(n)的算法。
冒泡排序是一种典型的交换排序算法,通过交换数据元素的位置进行排序。
时间复杂度O(N^2),额外的空间复杂度O(1),实现可以做到稳定性。
- 基本思想
冒泡排序的基本思想是:从无序序列头部开始,进行两两比较,根据大小交换位置,直到最后将最大(小)的数据元素交换到了序列的尾部,从而成为有序序列的一部分;下一次继续这个过程,直到所有数据元素都排好序。
算法的核心在于每次通过两两比较交换位置,选出剩余无序序列里最大(小)的数据元素放到尾部。
下面我们来看一下冒泡排序的简单例子(将序列按从小到大排):
假设有一个无序序列 { 5, 1, 7, 2, 9 }
第一趟排序:通过两两比较,找到第一大的数值 9 ,将其放在序列的末尾。{ 1, 5, 2, 7, 9 }
第二趟排序:通过两两比较,找到第二大的数值 7 ,将其放在序列的倒数第二位。{ 1, 2, 5, 7, 9 }
第三趟排序:通过两两比较,找到第三大的数值 5 ,将其放在序列的倒数第三位。{ 1, 2, 5, 7, 9 }
...
所有元素已经有序,排序结束。
其实,流程大致是:
在0-(n-1)进行操作
在0-(n-2)进行操作
在0-(n-3)进行操作
...
直到遍历结束,序列最终有序。
- 代码转换
假设要对一个大小为 n 的无序序列进行升序排序(即从小到大排列)。
(1)因为遍历第一次需要找到 0-(n-1)上最大的值,第二次遍历需要找到 0 - (n-2)上最大的值,因此,需要设置一个外循环,用来进行遍历;
(2)在遍历过程中,需要进行两两比较(第一次需要从0-(n-2)进行两两比较,第二次需要从0-(n-3)进行两两比较),因此,需要设置一个内循环来进行两两之间的比较;
(3)单独考虑特殊情况,数组长度为0或者小于2(即1)时不作处理。
以下是java代码的实现:
1 public class BubbleSort { 2 3 @Test 4 public void bubbleSort(int arr[]) { 5 //数组为空或者只有一个元素,直接返回 6 if(arr==null || arr.length<2) { 7 return; 8 } 9 else { 10 //end代表每次将0-end元素中最大的数放到end上,直到第一个元素 11 for(int end=arr.length-1; end>=0; end--) { 12 //从0-(end-1)开始两两比较 13 for(int i=0; i<end; i++) { 14 if(arr[i]>arr[i+1]) 15 swap(arr,i,i+1); 16 } 17 } 18 } 19 } 20 //交换两个数的方法 21 public void swap(int[] arr, int i, int j) { 22 int temp = arr[i]; 23 arr[i] = arr[j]; 24 arr[j] = temp; 25 } 26 }