分治策略实现快速排序法

来源:互联网 发布:剑雨江湖坐骑升级数据 编辑:程序博客网 时间:2024/05/18 02:44

说到算法,暑假就要去实习了,这时才感觉到数据结构和算法的重要性,虽然大二时候已经学过,但是基本用不到,导致现在基本忘了,现在重新拾起,重新把以前学过的和没有学过的算法都理一遍实现一遍!!!


快速排序算法:是对冒泡排序的一种改进,若初始记录序列按关键字pivotNum有序或基本有序,则将会蜕化为冒泡排序,此时时间复杂度为O(n²)。否则其平均时间复杂度为O(n longn) ,它使用的是递归原理,在所有同数量级O(n longn) 的排序方法中,其平均性能最好。就平均时间而言,是目前被认为最好的一种内部排序方法,它是不稳定的。

基本思想是

1.先从数组中取一个数作为基准数。

2.分区过程,先从后往前找,再从前往后找,将比这个基准数大的数全放到它的右边,小于它的数全放到它的左边,等于它的数位置不变,在这个分区过程结束时,该基准数的位置就处于数组中间的位置

3.再对左右区间重复第二步(递归进行),直到各区间只有一个数,这时排序完毕。

关于取哪个数作为基准数,这个不建议取第一个,建议随机取一个数作为基准数,这样取只是为了防止极端现象,可以防止当一个数组基本有序时,如果还是取第一个,那么快排的时间复杂度则退化为O(n²),如果每次都随机取一个数为基准数,那么可以避免这种现象。

看看演示图:



下面为更好理解,我就以取第一个数为基准数来演示:



把整个序列看做一个数组,把第零个位置作为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



1 0
原创粉丝点击