快速排序 [Java实现]

快速排序又被称为分割交换排序,是目前公认最佳的排序方法。它的原理和冒泡排序一样都是用交换的方式,不过它会现在数据中找到一个虚拟的中间值作为基准数,把小于这个基准数的数据放到它的左边,大于这个基准数的数据放到它的右边,再以递归的方式处理这个基准数左右两边的数据,直到完成为止。

假设我们有一组数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     }

这样,我们的快速排序算法就写完啦

我们将举例的一组数据输入,来测试一下:

你学会了吗?

猜你喜欢

转载自www.cnblogs.com/Miic517x/p/9088722.html