快速排序又被称为分割交换排序,是目前公认最佳的排序方法。它的原理和冒泡排序一样都是用交换的方式,不过它会现在数据中找到一个虚拟的中间值作为基准数,把小于这个基准数的数据放到它的左边,大于这个基准数的数据放到它的右边,再以递归的方式处理这个基准数左右两边的数据,直到完成为止。
假设我们有一组数56,18,6,3,97,66,8,26,88,30,99,93
第一轮,我们将56视为基准数
将大于它的数据放到它的右边,小于它的数据放到它的左边
再将最左侧的8视为基准数,将大于它的数据放到它的右边,小于它的数据放到它的左边
再选定6为基准数
左侧只剩一个3,不用排它也已经归为
我们再来排8的右侧,以18为基准数
这样,18就归归位了,它的左侧没有其它数字,那么我们再看它的右边,以30为基准数
排序过后左边就完成了
右边同理
不断的把左侧第一个数据当作基准数,一个一个地归为
通过上述图解,我们应该理解了快速排序的基本思路,这样我们就可以写出一个大致的框架:
1 //将索引left到right区间的下标元素进行快速排序 2 public static void quickSort(int[] arr,int left,int right) { 3 if(left>=right)return;//如果left大于等于right,方法结束 4 int p = arr[left];//设置最左边的元素为基准点 5 6 7 ··· ···//把序列当中比p大的放到右边,比p小的 8 ··· ···//放到左边,p放置在下标为i的位置 9 10 11 quickSort(arr,left,i-1);//对序列中i左边的元素实施快速排序 12 quickSort(arr,i+1,right);//对序列中i右边的元素实施快速排序 13 }
大致框架写好了,我们所要研究的就是中间的代码,怎样做到基准数的左侧都小于它,右侧都大于它呢?我们先用图片的方式来看一下:
首先我们设置两个循环变量,i 指向最左边,j 指向最右边,变量 p 的值为最左边的元素的值
先让 j 向左移动,一直到碰到一个比 p 的值小的元素
再让 i 向右移动,一直到碰到一个比 p 的值大的元素
这两个元素交换一下位置
接着我们重复之前的行为,让 j 继续向左移动,一直到它再次碰到一个比 p 值小的元素
然后,i 再向右移动,一直到它再次碰到一个比 p 值大的元素
找到之后,再交换一下
接着我们继续让 j 去找比p小的值,让 i 去找比p大的值
当我们发现,i 等于 j 时,交换 p 和 j 的元素,
这样,我们的第一轮排序就完成了
我们通过代码来实现一下这一轮所进行的行为:
1 //设置最左边的元素为基准点 2 int p = arr[left]; 3 4 //把要排序的序列中比p大的放到右边,比p小的放到左边,p的下标位置为i 5 int i = left,j=right; 6 while(i!=j) { 7 //j向左移动,找到一个比p小的元素 8 while(arr[j]>=p && i<j) { 9 j--; 10 } 11 //i向右移动,找到一个比p大的元素 12 while(arr[i]<=p && i<j) { 13 i++; 14 } 15 //i和j交换,如果i>j则不交换 16 if(i<j) { 17 int temp = arr[i]; 18 arr[i] = arr[j]; 19 arr[j] = temp; 20 } 21 } 22 //将j找到的最后一个比p小的值与基准值交换 23 arr[left] = arr[i]; 24 arr[i] = p;
我们再将这段代码套入之前的框架
1 public static void quickSort(int[] arr,int left,int right) { 2 //如果left大于等于right,则需要排序的部分至多只有一个元素,方法结束 3 if(left>=right) { 4 return; 5 } 6 //设置最左边的元素为基准点 7 int p = arr[left]; 8 9 //把要排序的序列中比p大的放到右边,比p小的放到左边,p的下标位置为i 10 int i = left,j=right; 11 while(i!=j) { 12 //j向左移动,找到一个比p小的元素 13 while(arr[j]>=p && i<j) { 14 j--; 15 } 16 //i向右移动,找到一个比p大的元素 17 while(arr[i]<=p && i<j) { 18 i++; 19 } 20 //i和j交换,如果i等于j则不用再交换 21 if(i<j) { 22 int temp = arr[i]; 23 arr[i] = arr[j]; 24 arr[j] = temp; 25 } 26 } 27 //将j找到的最后一个比p小的值与基准值交换 28 arr[left] = arr[i]; 29 arr[i] = p; 30 31 //对序列中,j左边的元素实施快速排序 32 quickSort(arr,left,i-1); 33 //对序列中,j右边的元素实施快速排序 34 quickSort(arr,i+1,right);35 }
这样,我们的快速排序算法就写完啦
我们将举例的一组数据输入,来测试一下:
你学会了吗?