说到算法,暑假就要去实习了,这时才感觉到数据结构和算法的重要性,虽然大二时候已经学过,但是基本用不到,导致现在基本忘了,现在重新拾起,重新把以前学过的和没有学过的算法都理一遍实现一遍!!!
给自己一个任务——每天一个算法!!!
快速排序算法:是对冒泡排序的一种改进,若初始记录序列按关键字pivotNum有序或基本有序,则将会蜕化为冒泡排序,此时时间复杂度为O(n2)。否则其平均时间复杂度为O(n longn) ,它使用的是递归原理,在所有同数量级O(n longn) 的排序方法中,其平均性能最好。就平均时间而言,是目前被认为最好的一种内部排序方法,它是不稳定的。
基本思想是:
1.先从数组中取一个数作为基准数。
2.分区过程,先从后往前找,再从前往后找,将比这个基准数大的数全放到它的右边,小于它的数全放到它的左边,等于它的数位置不变,在这个分区过程结束时,该基准数的位置就处于数组中间的位置。
3.再对左右区间重复第二步(递归进行),直到各区间只有一个数,这时排序完毕。
关于取哪个数作为基准数,这个不建议取第一个,建议随机取一个数作为基准数,这样取只是为了防止极端现象,可以防止当一个数组基本有序时,如果还是取第一个,那么快排的时间复杂度则退化为O(n2),如果每次都随机取一个数为基准数,那么可以避免这种现象。看看演示图:
下面为更好理解,我就以取第一个数为基准数来演示:
把整个序列看做一个数组,把第零个位置作为pivotNum,先从后面往前找,即首先和最后一个比,如果比它小交换,比它大不做任何处理,交换了以后再从前往后找,即和第一个元素比,比它小不交换,比他大交换。这样循环往复,一趟排序完成,左边就是比中轴pivotNum小的,右边就是比中轴pivotNum大的,然后再用分治法,分别对这两个独立的数组再进行快速排序,如此往复循环,直至每个数组中只有一个元素才排序完成。
进行排序一趟的代码为:
public static int sort(int[] data,int left,int right){//每次进行一趟排序 int pivotNum = data[left]; while(left<right){ while(left<right && data[right]>=pivotNum){ right--; } data[left] = data[right];//将比轴点小的数移到左端,此时right位相当于空,等待左边比pivotNum大的数赋予它 while(left<right && data[left]<=pivotNum){ left++; } data[right] = data[left];//将比轴点大的数移到右端,此时left位相当于空,等待右边比pivotNum小的数赋予它 } //此时left==right,完成了一躺排序,此时left位相当于空,等待轴点那个数pivotNum补上 data[left] = pivotNum; //此时返回的lefr即为中间的位置 return left; }递归的实现快速排序:
public static void quickSort(int[] nums,int left,int right){ if(isEmpty(nums)) return; if(left<right){ //middle作为中间的位置,比它所在位置的元素小的元素在左边作为一个数组再进行排序,比它所在位置的元素大的元素在右作为一个数组进行排序 int middle = sort(nums, left, right);//将list数组进行一分为二,然后分别递归排序 //对左、右数组递归调用快速排序,直到排序完成 quickSort(nums, left, middle-1); quickSort(nums, middle+1, right); } }
public class QuickSort { public static int sort(int[] data,int left,int right){//每次进行一趟排序 int pivotNum = data[left]; while(left<right){ while(left<right && data[right]>=pivotNum){ right--; } data[left] = data[right];//将比轴点小的数移到左端,此时right位相当于空,等待左边比pivotNum大的数赋予它 while(left<right && data[left]<=pivotNum){ left++; } data[right] = data[left];//将比轴点大的数移到右端,此时left位相当于空,等待右边比pivotNum小的数赋予它 } //此时left==right,完成了一躺排序,此时left位相当于空,等待轴点那个数pivotNum补上 data[left] = pivotNum; //此时返回的lefr即为中间的位置 return left; } public static void quickSort(int[] nums,int left,int right){ if(isEmpty(nums)) return; if(left<right){ //middle作为中间的位置,比它所在位置的元素小的元素在左边作为一个数组再进行排序,比它所在位置的元素大的元素在右作为一个数组进行排序 int middle = sort(nums, left, right);//将list数组进行一分为二,然后分别递归排序 //对左、右数组递归调用快速排序,直到排序完成 quickSort(nums, left, middle-1); quickSort(nums, middle+1, right); } } public static boolean isEmpty(int[] nums){ if(nums.length==0){ return true; } return false; } }
输入:17 31 40 26 35 36 25 12 2 38
输出:2 12 17 25 26 31 35 36 38 40
原文地址:http://blog.csdn.net/u010687392/article/details/46044043