随机化快速排序的分治实现(java)

一,为什么要进行随机化快速排序?

快速排序的时间复杂度为:
最好的情况:O(nlogn)

最坏的情况:O(n^{2})

由此我们可知,时间复杂度会因为固定主元的选取和次序的不一致而发生变化,如何摆脱输入导致最坏情况。

数组划分时选取固定位置主元,可以针对性构造最差情况。

数组划分时选取随机位置主元,无法针对性构造最差情况。

二,了解分治思想在快速排序中的实现

1,归并排序:重在合并,合并子问题

2,快速排序:侧重分解,简化合并

3,由此可见,分治思想在快速排序中的重点就是数组划分

 三,数组划分伪代码

 四,快速排序伪代码

 五,代码编译

1,代码框架

import java.util.Arrays;

public class QuickSort {
    public void ToQuickSort(int[] arr,int p,int q){

    }
    public int Partition(int[] arr,int p,int r){
        
    }
    public static void main(String[] args) {
        QuickSort quicksort=new QuickSort();
        int[] arr={2,1,3,4,7,5,6,6};
        System.out.println(Arrays.toString(arr));
        quicksort.ToQuickSort(arr,0,arr.length-1);
        System.out.println(Arrays.toString(arr));
    }
}

2,如何生成随机数

在Java语言中生成随机数相对来说比较简单,因为有一个现成的方法可以使用。在Math类中,Java语言提供了一个叫做random的方法。通过这个方法可以让系统产生随机数。不过默认情况下,其产生的随机数范围比较小,为大于等于0到小于1的double型随机数。虽然其随机数产生的范围比较小,不能够满足日常的需求。如日常工作中可能需要产生整数的随机数。其实,只要对这个方法进行一些灵活的处理,就可以获取任意范围的随机数。
  如我们可以先通过random方法生成一个随机数,然后将结果乘以10。此时产生的随机数字即为大于等于0小于10的数字。然后再利用Int方法进行转换(它会去掉小数掉后面的数字,即只获取整数部分,不是四舍五入)。最后即可获取一个0到9的整数型随机数字。其实现方法很简单,就是对原有的random方法按照如下的格式进行变型:(int)(Math.Random()*10)即可。其实我们还可以对这个方法进行扩展,让其产生任意范围内的随机数。至需要将这个10换成n即可,如改为(int)(Math.Random()*n)。此时应用程序就会产生一个大于等于0小与n之间的随机数。如将n设置为5,那么其就会产生一个0到5之间的整数型的随机数。如果将这个写成一个带参数的方法,那么只要用户输入需要生成随机数的最大值,就可以让这个方法来生成制定范围的随机数。注:这里random的取值范围始终是[0,n),如果要生成负随机数,就0-(int)(Math.Random()*n),这样就生成(-n,0]的随机数了。

3,一次数组划分后的步骤

再根据伪代码进行分治求解就出来了。

 4,完整代码

import java.util.Arrays;
public class QuickSort {
    public void ToQuickSort(int[] arr,int p,int r){
        if(p<r){
            int q=Partition(arr,p,r);
            ToQuickSort(arr,p,q-1);
            ToQuickSort(arr,q+1,r);
        }//递归入口(p<r)和出口
    }
    public int Partition(int[] arr,int p,int r){
        //取一个范围在[0,r-p+1)的随机数,本题中范围为[0,8),然后递归求解
        int RandomLocation=p+(int)(Math.random()*(r-p+1));
        //把随机主元放在数组末尾
        int temp=arr[RandomLocation];
        arr[RandomLocation]=arr[r];
        arr[r]=temp;
        int x=arr[r];
        //数组中的元素和主元比较
        int i=p-1;//i代表较小元素的集合坐标,j代表较大元素的集合坐标
        for(int j=p;j<=r-1;j++){
            if(arr[j]<=x){
                int temp1=arr[i+1];
                arr[i+1]=arr[j];
                arr[j]=temp1;
                i=i+1;/*!第一次编译出现错误的地方,i没有向后递加!*/
            }
        }
        //把主元放在适当位置
        int temp2=arr[i+1];
        arr[i+1]=arr[r];
        arr[r]=temp2;
        return i+1;//返回划分位置
    }
    public static void main(String[] args) {
        QuickSort quicksort=new QuickSort();
        int[] arr={2,1,3,4,7,5,6,6};
        System.out.println(Arrays.toString(arr));
        quicksort.ToQuickSort(arr,0,arr.length-1);
        System.out.println(Arrays.toString(arr));
    }
}

 5,出现问题

主要集中在划分位置函数Partition

    public int Partition(int[] arr,int p,int r){
        //取一个范围在[0,r-p+1)的随机数,本题中范围为[0,8),然后递归求解
        int RandomLocation=p+(int)(Math.random()*(r-p+1));
        //把随机主元放在数组末尾
        int temp=arr[RandomLocation];
        arr[RandomLocation]=arr[r];
        arr[r]=temp;
        int x=arr[r];
        //数组中的元素和主元比较
        int i=p-1;//i代表较小元素的集合坐标,j代表较大元素的集合坐标
        for(int j=p;j<=r-1;j++){
            if(arr[j]<=x){
                int temp1=arr[i+1];
                arr[i+1]=arr[j];
                arr[j]=temp1;
                i=i+1;/*!第一次编译出现错误的地方,i没有向后递加!*/
            }
        }
        //把主元放在适当位置
        int temp2=arr[i+1];
        arr[i+1]=arr[r];
        arr[r]=temp2;
        return i+1;//返回划分位置
    }
int RandomLocation=p+(int)(Math.random()*(r-p+1));

 这里给随机位置加上p,p是数组的首元素,对数组划分后数组一分为二,如果不加p,对前一个数组没啥影响,但是后一个数组的首元素的位置就没法计算了,因此加上这个p的同时,用r-p+1来计算数组的长度,这样后一个数组的随机位置划分也就可以计算了。


 

int temp=arr[RandomLocation];
arr[RandomLocation]=arr[r];
arr[r]=temp;
int x=arr[r];

 这里将随机主元放在数组末尾,也就是默认以末尾为固定主元的方式来快排,随机主元的设定只是对划分位置进行随机,快排方式不变。

数组结束排列后,还要将随机主元放回合适的位置,然后进行下一次递归。


for(int j=p;j<=r-1;j++){
    if(arr[j]<=x){
        int temp1=arr[i+1];
        arr[i+1]=arr[j];
        arr[j]=temp1;
        i=i+1;/*!第一次编译出现错误的地方,i没有向后递加!*/
    }
}

 i和j要根据情况进行变化。

  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
随机化快速排序(Randomized QuickSort)是一种基于比较的排序算法,它通过随机选择一个元素作为枢纽(pivot)来进行分区(partition),从而实现对数组的排序。下面是随机化快速排序Java实现: ```java import java.util.Random; public class RandomizedQuickSort { public static void main(String[] args) { int[] arr = {5, 2, 9, 1, 7, 6, 3}; quickSort(arr, 0, arr.length - 1); for (int num : arr) { System.out.print(num + " "); } } public static void quickSort(int[] arr, int low, int high) { if (low < high) { int pivotIndex = partition(arr, low, high); quickSort(arr, low, pivotIndex - 1); quickSort(arr, pivotIndex + 1, high); } } public static int partition(int[] arr, int low, int high) { // 随机选择枢纽 Random random = new Random(); int randomIndex = random.nextInt(high - low + 1) + low; swap(arr, randomIndex, high); int pivot = arr[high]; int i = low - 1; for (int j = low; j < high; j++) { if (arr[j] < pivot) { i++; swap(arr, i, j); } } swap(arr, i + 1, high); return i + 1; } public static void swap(int[] arr, int i, int j) { int temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; } } ``` 以上是一个简单的随机化快速排序Java实现。它通过递归地对分区进行排序,直到最终完成整个数组的排序。在每次分区时,随机选择一个元素作为枢纽,将小于枢纽的元素放在枢纽的左边,大于枢纽的元素放在枢纽的右边。然后再对左右两个分区进行递归排序。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值