算法之快速排序
初学算法,基础较弱,如果有不足或是不正确的地方,希望多多包涵,多多指正。
一.基本思想
快速排序是对冒泡排序的一种改进。通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的数据都比另一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快排序。整个过程进行递归,从而将数据序列变成有序序列。
二.算法图解
三.算法实现思路
1.设置两个索引值,一个指向左索引 left,一个指向右索引right;
2.取中间值mid=arr[(left+right)/2],并设置临时变量temp;
3.利用循环从中间值左边找到比mid值大的数,从中间值右边找到比mid小的数,二者交换,同时形成两个新的子表;
4.然后向左递归处理mid左边的数据,向右递归处理mid右边的数,对左右子表分别按步骤2、3进行快速排序处理,直至数据有序。
四.代码实现
public class QuickSort {
public static void quickSort(int arr[],int left ,int right){
int l=left; //设置左下标
int r=right; //设置右下标
int temp=0; //设置临时变量
int mid=arr[(left+right)/2]; //设置中间值
//while循环将比mid小的值放到左边,比mid大的值放到右边
while (l<r){
while (arr[l]<mid){
l+=1;
}
while (arr[r]>mid){
r-=1;
}
if (l>r){
break;
}
//交换数据
temp=arr[l];
arr[l]=arr[r];
arr[r]=temp;
//如果交换后 arr[l]==mid的值,则前移
if (l<r && arr[l]==mid){ //此处l<r,防止越界
r--;
}
//如果交换后 arr[r]==mid的值,则后移
if (l<r && arr[r]==mid){
l++;
}
}
//若l==r,则进行l++,r--,防止栈溢出
if (l==r){
l +=1;
r -=1;
}
//向左递归处理左子表
if (left<r){
quickSort(arr,left,r);
}
//向右递归处理右子表
if (right>l){
quickSort(arr,l,right);
}
}
//初始化一个数组,对结果进行测试
public static void main(String[] args) {
int arr[]={32,48,-10,0,45,-20,9,25,26};
System.out.println("排序前的序列为:" + Arrays.toString(arr));
quickSort(arr,0,arr.length-1); //注意防止数组越界异常
System.out.println("排序后的序列为:" + Arrays.toString(arr));
}
}
五.算法结果截图
六.算法分析
1.时间复杂度
**最好情况:**每次划分时的中间值恰好将当前序列几乎等分,经过 log2n趟划分,便可以排序完毕。这样,所以理想状态下整个算法的时间复杂度为 O(nlog2n)。
**最坏的情况:**每次所选的中间数是当前序列中的最大或最小元素,这样,长度为n的数据表的快速排序需要经过n趟划分,使得整个排序算法的时间复杂度为O(n^2),与冒泡排序相当。
2.空间复杂度
快速排序使用的数据空间是O(1),但在递归调用时会消耗空间,因为每次递归就要保存一些数据,所以
最优的情况下空间复杂度为:O(logn) ,此时是每一次都平分数组的情况
最差的情况下空间复杂度为:O( n ) ,此时退化为冒泡排序的情况
3.稳定性
由于在排序过程中会有多次递归处理数据,所以该排序 不稳定