冒泡排序的优化 下面这个是最常见的冒泡排序的写法: 每次将最大的数冒泡到顶部,时间复杂度为O(n**2)
public void bubble_sort(int[] a,int n) { for(int i=0;i<n;i++) for(int j = 1;j<n-i;j++) { if(a[j-1]>a[j]){ int temp=a[j-1]; a[j-1]=a[j]; a[j]=temp; } } }那么如何对冒泡排序的时间复杂度进行优化呢? 既然要进行优化,就要从冒泡排序的复杂性开始讨论。 例如数组{3,2,4,5,6}。经过第一轮排序其实就已经有序了,但是冒泡排序还会进行接下来的几轮排序。所以可以从这个点上进行优化,检验是否数组已经有序,保证不进行无调整的排序。 下面是优化版的代码
public void bubbleSort_plus(int[] arr){ boolean flag=true; for(int i=0;i<arr.length-1&&flag;i++){ flag=false; for(int j=arr.length-1;j>i;j--){ if(arr[j]<arr[j-1]){ flag=true; int tmp=arr[j]; arr[j]=arr[j-1]; arr[j-1]=tmp; } } } }利用boolean定义一个flag变量,用来检查已完成的排序是否已经有序,如果有序,flag不会被赋值为true,下次不会再进入循环,可以省略掉多余的排序次数。 选择排序的优化 下面是传统的选择排序,每次从要排序数组中选出最小的值,每经过1轮排序,将这一轮的最小值min与parr[i]换位。将要排序数组向前移动一位。 时间复杂度O(n**2)
public void SelectSort(int[] arr)//选择排序(升序) { int size=arr.length; for (int i = 0; i < size; i++){ int min = parr [i]; for (int j = i + 1; j < size; j++){ if (parr [j]<min){ int temp=min; min=parr[j]; parr[j]=temp; } } if (min!=parr [i]) { int temp1=min; min=parr[i]; parr[i]=temp1; } } }下面是选择排序的优化算法 思考算法的优化就要思考有哪里可以优化,选择排序是选出没次排序数组中的最小值,以达到排序的目的,那么既然可以选择每次排序的最小值,是不是也可以找出每次排序的最大值,那么,一次就确定了两个位置,就大大地提升了排序的效率。优化后的选择排序时间复杂度为O(n*logn) 下面是代码
public void SelectSort(int[] parr)//选择排序(优化方案){ int size=parr.length; int left; int right; int temp; for (left = 0,right = size - 1; left < right; left++, right--;{ int min = parr[left]; int max = parr[right]; for (int i = left+1; i <= right; i++)//遍历找出最大和最小元素{ if (min>parr[i]) { temp=min; min=parr[i]; parr[i]=temp; } else if (parr[i] > max) { temp=max; max=parr[i]; parr[i]=temp; } } if (min != parr[left]){ temp=min; min=parr[left]; parr[left]=temp; if (max == parr[left]){ max = min; } } if (max != parr[right]){ temp=max; max=parr[right]; parr[right]==temp; if (min == parr[right]){ min = max; } } } }插入排序的优化 关于插入排序,算法导论上有一个很形象的例子,比如斗地主的摸牌阶段,你每摸一张牌,就是从左往右,或者从右往左,找到适合它大小的位置插入,这就是一个插入排序的过程。 所以当进行完了第n轮排序,会保证前n个数有序。(从左向右插入的情况) 时间复杂度O(n**2) 以下是代码:
public void insertSort3(int a[]) { int i; int tmp; int j; int len=a.length; for (i = 1; i < len; i ++) for(j = i; j > 0 && a[j - 1] > a[j]; j--) { tmp = a[j - 1]; a[j - 1] = a[j]; a[j] = tmp; } }要想优化插入排序,也首先从过程开始分析,像一个有序数组中找到一个合适的位置,插入一个新的元素,插入排序中实现这个目的是遍历,所以时间复杂度较高,那么有序数组中找到合适位置,是不是会想到二分查找呢。所以有了优化的方案。 通过二分查找,以logn的时间复杂度可以找到需要插入的位置,优化后的插入排序的时间复杂度为O(n*logn) 以下是代码
public static void insertSort2(int[] a) { for (int i = 0; i < a.length-1; i++) { int temp=a[i+1]; int low=0; int high=i; int mid; //在low和high之间的区域进行二分查找,找到新插入的元素位置 while(low<=high){ mid=(low+high)/2; if(a[mid]>temp){ high=mid-1; }else{ low=mid+1; } } //经过上面的二分查找,得到新元素的位置是:high+1 //把[high+1,i]区间内的所有元素往后移一个位置 for (int j = i; j > high; j--) { a[j+1]=a[j]; } a[high+1]=temp; } }总结了三种最基本的排序算法的优化,想说一下,自己对优化算法的理解。要想优化一个算法,首先要细化算法的实现,找出其中复杂的地方,用更简单的方法去实现。当然这些东西说起来比较简单,实现起来需要很多经验的积累。优化不光是时间复杂度,空间复杂度,包括很多处理上都可以尝试去优化。总之,算法的坑还是很深的,关于算法优化的例子,我以后还会继续总结的。