1、什么是快速排序?

 

 

快速排序和冒泡排序都是采用交换法,与冒泡不同的是,快速排序还采用分治法:通过选定一个“基点(可随机选择)”,将小于基点的元素放在基点左侧,大于基点的放在右侧,然后用递归对基点两侧的元素再排序

2、快速排序的代码思路:

  双边循环法:

    • 假定基点pivot是数组最左侧元素,设置两个指针left,right分别指向待排元素最左侧和最右侧
    • left开始向右移动,如果left指向的数大于基点,停止移动
    • right开始移动,如果right指向的数小于基点,停止移动 
    • arr[left]和arr[right]交换位置
    • 如果left==right,第一轮分治结束,将基点pivot与arr[left]交换位置,接下来进行左边和右边的分治

3、双边循环法代码实现:

//目标:排序数组内元素
 int[] arr={-9,78,0,23};
public static void quickSort(int[] arr,int startIndex,int endIndex) {
        if (startIndex>=endIndex){  //一般都是=的时候结束
            return;
        }

        int pivotIndex=singlePartition(arr,startIndex,endIndex);

        quickSort(arr,startIndex,pivotIndex-1);
        quickSort(arr,startIndex+1, endIndex);
    }
 public static int  partition(int[] arr,int startIndex,int endIndex){
        int pivot=arr[startIndex];  //假定的基点
        int left=startIndex;   //左边移动的指针
        int right=endIndex;  //右边移动的指针

        while (left!=right){   //左边不等于右边,说明还没有移动完
            while (left<right && arr[right]>=pivot){  //left<right是个限定,arr[right]>=pivot 是右边指针left指向的元素比基点大,左移,因为基点右边的本来就该比基点大,我们找的是右边开始小于基点的
                right--;
            }
            while (left<right && arr[left]<=pivot){  //寻找左边开始大于基点的,找不到就后移,直到找到跳出
                left++;
            }

            if (left<right){  //跳出后执行交换,这就把左边大的转移到了右边,右边小的转移到了左边
                int p=arr[left];
                arr[left]=arr[right];
                arr[right]=p;
            }
        }
        //当left==right时,交换left指向的元素和基点的位置
        arr[startIndex]=arr[left];
        arr[left]=pivot;
        return left;  //这里返回的left主要时为了确定左右递归时的结束位置和开始位置
    }

 4、单边循环法

  4.1 代码思路:

    • 选择基准元素pivot,设置mark指针指向数列起始位置
    • 遍历的元素大于基准元素,继续向后遍历
    • 遍历元素小于基准元素,指针mark右移,将遍历元素和mark指向的元素交换位置
    • 遍历完数列后,基准元素和mark指向的元素交换位置,这就分成了两队(左边小于基准元素,右边大于基准元素)
    • 递归排序左边和右边的待排数列

  4.2 代码实现

 public static int singlePartition(int[] arr,int startIndex,int endIndex){
        int pivot=arr[startIndex];    //设置基准元素
        int mark=startIndex;   //mark指针

        for (int i=startIndex+1;i<endIndex;i++){  //遍历基准元素后面的数列
            if (arr[i]<mark){    //如果当前元素大于基准元素,mark后移,并让mark指向的元素和当前元素交换位置
                mark++;  
                int p=arr[mark];
                arr[mark]=arr[i];
                arr[i]=p;
            }
        }
        //遍历完成,mark和基准元素交换位置
        arr[startIndex]=arr[mark];   
        arr[mark]= pivot;
        return mark;   
    }

5、快速排序时间复杂度

O(nlogn)

版权声明:本文为han200113原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/han200113/p/11729309.html