快速排序作为很经典的一种排序方法,我们怎么能不掌握呢?
首先让我们来理清快速排序的思路:
现在有一个数组如下:
int[] nums = {4,1,6,2,3,7,9,8,0,5} ;
我们要使用快速排序使这个数组变的有序,从小到大或者从大到小的顺序进行排列。其思路就是每次选择数组中的一个数作为”基数“,以这个”基数“作为标准,将数组分为两个部分,例如:将小于等于这个”基数“的数放在”基数“的左边,而把大于”基数“的数放在基数的右边,这样就可以让数组变成一个”相对有序”的状态,然后继续分别对这两个部分重复之前的操作直到所划分的部分只有一个元素的时候,整个数组就是有序的了,这样看文字的描述确实不够清楚,下面让我们通过数据变化的过程来理解一下(例子是上面数组):
选择4作为基数,将数组分为小于等于4的和大于4的两个部分
0 1 3 2 4 7 9 8 6 5
对于小于等于4的部分,选择0作为基数,没有比0小的了,所以数组没有变化
0 1 3 2 4 7 9 8 6 5
对于大于0,小于等于4的部分,选择1作为基数,没有比1小的了,所以数组没有变化
0 1 3 2 4 7 9 8 6 5
对于大于1,小于等于4的部分,选择3作为基数,2放到3的前面,至此,0->4部分的数已经完全有序了
0 1 2 3 4 7 9 8 6 5
选择7作为基数:
0 1 2 3 4 5 6 7 8 9
选择5作为基数:
0 1 2 3 4 5 6 7 8 9
选择8作为基数:
0 1 2 3 4 5 6 7 8 9
看完整个快速排序的过程,相信大家就已经很清楚快速排序的思想了,那么我们紧接着使用代码来将这个思路实现吧!
public void quickSort(int[] nums,int s,int e) {
if (s >= e) {
return;
}
int partitionFlag = partition(nums,s,e);
quickSort(nums,s,partitionFlag-1);
quickSort(nums,partitionFlag+1,e);
}
private int partition(int[] nums,int s,int e) {
//优化:选择一个相对来说是中间大小的数作为基数
int mid = s + (e-s>>1);
if (nums[s] > nums[e]) {
swap(nums,s,e);
}
if (nums[mid] > nums[e]) {
swap(nums,mid,e);
}
if (nums[s] < nums[mid]) {
swap(nums,s,mid);
}
int temp = nums[s];
System.out.print("选择"+temp+"作为基数:"+"\n");
while (s < e) {
//找小于等于基数的数
while (nums[e] > temp && s < e) {
e--;
}
if (s < e) {
nums[s++] = nums[e];
}
//找大于基数的数
while (nums[s] <= temp && s < e) {
s++;
}
if (s < e) {
nums[e--] = nums[s];
}
}
//将基数放在合适的位置
nums[s] = temp;
for (int i : nums) {
System.out.print(i + " ");
}
System.out.println();
return s;
}
private void swap(int[] nums,int x,int y) {
int temp = nums[x];
nums[x] = nums[y];
nums[y] = temp;
}
其中有个优化的点可以注意一下,之前我们是选择基数是直接使用的第一个数,这样带来的问题就是,选择的基数可能已经是索要判断的部分的最大或者最小的值了,这会导致这一轮的排序没有任何的变化,比如我们之前的看到的选择0和1作为基数时数组都没有任何改变。那么如果我们每次选择的基数都是一个相对“中间”的数,那么我们的每一轮排序都会有效很多,这样可以提高不少效率!
如果我写的有问题的地方,还望各位指正,欢迎大家跟我交流。