快速排序
对冒泡排序的一种改进
通过一趟排序将数据分为两部分
其中一部分的所有数据都要小于另一部分数据
再递归进行上述过程,
直到整个数据都变成有序队列
最坏情况下,时间复杂度为O(n^2)
平均复杂度:O(NlogN) 二分思想
思路分析:
(参考五分钟学算法)
left->22 16 56 63 62 54 61 26 19 2 <-right
第一步,找到中轴值,这里设为left指向的元素22,节省一次交换
第二步,从右指针开始向左遍历直到找到比中轴值小的数,赋值给左指针,再交替遍历左指针找到比中轴值大的数赋值给右指针,直到左右指针相遇
(如果有相等的数,需要在交换后移动被交换指针防止死循环)
eg 21111112
左指针指向2
右指针也指向2
这里将右指针的2赋值给左指针的2如果不移动左指针会导致死循环
所以赋值后移动左指针,指针也是同理,交换后需要移动右指针
left->22 16 56 63 62 54 61 26 19 2 <-right
重新回到原来的案例
右指针开始遍历直到找到2停下,并赋值给左指针此时为
left->2 16 56 63 62 54 61 26 19 2 <-right
左指针开始遍历
直到碰到比22大的数字56停下
2 16 left->56 63 62 54 61 26 19 2 <-right
将56赋值给右指针
2 16 left->56 63 62 54 61 26 19 56<-right
右指针遍历
找到19停下赋值给左指针
2 16 left->19 63 62 54 61 26 19<-right 56
左指针遍历
找到63停下赋值给右指针
2 16 19 left-> 63 62 54 61 26 63<-right 56
右指针遍历
找到左指针停下
2 16 19 left->63<-right 62 54 61 26 63 56
此时就是中轴值所应处的位置,将最开始的中轴值22赋值给左指针得到第一次排序结果,此时22左侧都比22小,而22右侧都比22大
2 16 19 left->22<-right 62 54 61 26 63 56
于是对22左右分别重复上述操作,递归进行
直到排序的数组长度为1,即left>right,退出递归
代码如下:
public void quicksort(int left, int right, int[] arr) {
int orileft = left;
int oriright = right;
if (right < left) {
return;
}
int mid = arr[left];
while (left < right) {
while (arr[right] > mid && left < right) {
right--;
}
arr[left] = arr[right];
if(arr[left]==mid && left<right){
left++;
}
while (arr[left] < mid && left < right) {
left++;
}
arr[right] = arr[left];
if(arr[right]==mid && left<right){
right--;
}
if (left == right) {
arr[left] = mid;
break;
}
}
quicksort(orileft, left-1, arr);
quicksort(right+1, oriright, arr);
}
可以看到当排序数组缩小为1时,orileft=left>left-1
oright=right<right+1
退出递归
当排序数组大于等于2时,会对不包含中轴值的两块排序数组进行排序
总结:思路乍一想还比较简单,但是上手写时时常会出现多种多样的问题,常写常新才是正道