排序算法(快速排序)

一、基本思路

1.在当前要排序的区间选择一个基准值x,并令i指向区间最左,j指向区间最右

2.从该区间 j 的位置向左开始扫描,直到找到一个比基准值x小的, 将这个小的填到 i 的位置上,i++;

3.从该区间 i 的位置向右开始扫描,直到找到一个比基准值x大的,将这个大的填到 j 的位置上,j–;

4.重复2,3 直到 i 超过 j 或等于 j ,此时将基准值x填入a[ i ],至此,x左边的所有数都比 x 小,右边的所有数都比 x 大

5.以 i 为分界线,分别对区间 [ l ,i-1 ] ,[ i+1,r ]进行快排

二、例子

我们以{3,5,7,9,8,6,2,1,4,0}数组的排序为例子,我们可以将要被填的地方看成一个坑

1.令基准值为区间第一个,也就是x=3,i,j 的位置如下,此时i的位置是一个坑,需要被填,所以要从后面找一个比x小的来填

         i                                                                                                                                                                          j

3579862140

2.从 j 开始往左找一个比 x 小的,此时我们找到一个0,将0填到 i 这个坑的位置上,并将 i++ ,如下

                            i                                                                                                                                                       j

0579862140

此时由于 j 这个地方的数移到了前面,落下了一个坑,所以要从前面找一个比 x 大的数来填补这个坑

3.从i开始往右找一个比 x 大的,此时我们找到一个5,将5填到 j 这个坑的位置上,并将 j–,如下

                            i                                                                                                                                    j

0579862145

此时由于i这个地方的数移到了后面,又落下一个坑,所以要从后面找一个比 x 小的数来填补这个坑

2.从 j 开始往左找一个比 x 小的,此时我们找到一个1,将1填到i的位置上,并将 i++ ,如下

                                               i                                                                                              j

0179862145

3.从 i 开始往右找一个比 x 大的,此时我们找到一个7,将7填到j的位置上,并将 j– ,如下

                                               i                                                                           j

0179862745

2.从 j 开始往左找一个比 x 小的,此时我们找到一个2,将2填到i的位置上,并将 i++ ,如下

                                                                  i                                                        j

0129862745

3.从 i 开始往右找一个比 x 大的,此时我们找到一个9,将9填到j的位置上,并将 j–,如下

                                                                  i                                     j

0129869745

2.从j开始往左找一个比 x 小的,此时我们的j一直移到了i的那个位置,也找不到比3更小的了,我们将 i 的位置填上这个基准数

                                                                 i,j

0123869745

4.到了这一步,我们可以发现 i 位置的左边均比a[i]小,右边均比a[i]大 ,i=3

5. 继续对 [0,2],[4,9] 区间分别快排

三、代码实现

public class QuickSort {
	public static void main(String[] args) {
		int [] a=new int[]{3,5,7,9,8,6,2,1,4,0};
		QuickSort quickSort=new QuickSort();
		quickSort.quickSort(a,0,9);
		for(int item:a){
			System.out.print(item+" ");
		}
	}
	private void quickSort(int[] a, int l, int r) {
		if(l<r){
			int i=l,j=r,x=a[l];//定义基准数x(区间第一个),以及i,j指标
			while(i<j){
				while(i<j&&a[j]>=x)//从最右边开始找一个比x小的
					j--;  
				if(i<j)//此时j所指的数比x小
				a[i++]=a[j];
				while(i<j&&a[i]<=x)//从最左边开始找一个比x大或相等的
					i++;  
				if(i<j)//此时i所指的数比x大或相等
				a[j--]=a[i];	
			}
			a[i]=x; //一趟下来x左边的所有数比x小,...
			quickSort(a, l, i-1);
			quickSort(a, i+1, r);
		}
	}



}

四、复杂度

最优情况下,也就是每次选的基准值都是中位数,每次都划分得很均匀 ,此时时间复杂度为O(nlogn)

最差情况下,是待排序数组刚好是正序或逆序,如刚好是正序,那么每一次的基准值会填入在区间最左边,然后递归右边的子区间,如[ 1,9 ]、[ 2,9 ]、[ 3,9 ]、[ 4,9 ]、[ 5,9 ]……由于左边的区间是[0,-1],[1,0],[2,1],左大于右,故会终结递归,所以考虑到右边的区间递归,为 O(n²)

平均情况下,为O(nlogn)


点赞