java快速排序【vaynexiao】

概念和思想

  • 从数列中挑出一个元素,称为“基准”(pivot)

  • 分区(partition): 遍历数列,比基准小的元素放左边,比它大的放右边。
    于是此次分区结束后,该基准就处于数列的中间位置,其左边的数全比它小(称为小与子序列),右边的数全比他大(称为大于子序列)。这样一次排序就造成了整体上的有序化。

  • 子数列排序: 将小与子数列和大于子序列分别继续快速排序。

  • 递归到最底部时,数列的大小是零或一,至此就都排序好了,递归结束。
    在这里插入图片描述
    看了图就知道,其实就只将整体分为两区域,成为分区,即partition,而分界线也就是基准元素位置是就位的,接下来对左边分区和右边分区继续进行这个思路来partition,利用递归直至全部元素就位达到排序目的。

双边循环法 & 单边循环法

双边循环法

有很多方法,这是最基本最普通的方法
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
再来一个演示过程的图,加深理解
在这里插入图片描述

单边循环法

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

code

public class Tss {
    
    
    //main方法中将数组传入排序方法中处理,之后打印新的数组
    public static void main(String[] stra){
    
    
        int[] arr={
    
    7,0,3,5,4,6,2,8,1,9};
        quickSort(arr, 0, arr.length-1);
        for (int i=0;i<arr.length;i++) {
    
    
            System.out.print(arr[i]+"、");
        }
    }
    public static void quickSort(int[] arr, int startIndex, int endIndex) {
    
    
        // 递归结束条件:startIndex大于或等于endIndex时
        if (startIndex >= endIndex) {
    
    
            return;
        }
        // 得到基准元素位置
        int pivotIndex = partition2(arr, startIndex, endIndex);
        // 根据基准元素,分成两部分进行递归排序
        quickSort(arr, startIndex, pivotIndex - 1);
        quickSort(arr, pivotIndex + 1, endIndex);
    }
    /**
     * partition即就是进行一次分区,利用分治法,同时得到基准元素位置(双边循环法)
     */
    private static int partition(int[] arr, int startIndex, int endIndex) {
    
    
        // 取第1个位置(也可以选择随机位置)的元素作为基准元素
        int pivot = arr[startIndex];
        int left = startIndex;
        int right = endIndex;

        while( left != right) {
    
    
            //控制right 指针比较并左移
            while(left<right && arr[right] > pivot){
    
    
                right--;
            }
            //控制left指针比较并右移
            while( left<right && arr[left] <= pivot) {
    
    
                left++;
            }
            //交换left和right 指针所指向的元素
            if(left<right) {
    
    
                int temp = arr[left];
                arr[left] = arr[right];
                arr[right] = temp;
            }
        }
        //pivot 和指针重合点交换
        arr[startIndex] = arr[left];
        arr[left] = pivot;
        return left;
    }
    /**
     * partition即就是进行一次分区,利用分治法,同时得到基准元素位置(单边循环法)
     */
    private static int partition2(int[] arr, int startIndex, int endIndex) {
    
    
        // 取第1个位置(也可以选择随机位置)的元素作为基准元素
        int pivot = arr[startIndex];
        int mark = startIndex; //mark标记的是坐标,最后要将pivot和mark坐标元素swap,得到pivot分割后的左小右大两个区域

        for(int i=startIndex+1; i<=endIndex; i++){
    
    
            if(arr[i]<pivot){
    
    
                mark ++; // 每次+1,是统计有多少个小于pivot的元素,
                int p = arr[mark]; //同时将小于pivot的元素交换位置,交换到mark标记的左侧区域,也就是小于pivot的区域
                arr[mark] = arr[i];
                arr[i] = p;
            }
        }
        // 上面代码是为了分区,以及得到mark坐标,此时将pivot和mark元素交换,利用pivot分区完毕
        arr[startIndex] = arr[mark];
        arr[mark] = pivot;
        return mark;
    }
}

为什么叫快速排序

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/vayne_xiao/article/details/109167711