Algs4-2.3.24取样排序

2.3.24取样排序。(W.Frazer,A.McKellar)实现一个快速排序,取样大小为2^k-1.首先将取样得到的元素排序,然后在递归函数中使用样品的中位数切分。分为两部分的其余样品元素无需再次排序并可以分别应用于原数组的两个子数组。这种算法被称为取样排序。
2.3.24 Samplesort. ( W. Frazer and A. McKellar) Implement a quicksort based on using
a sample of size 2k 1. First, sort the sample, then arrange to have the recursive
routine partition on the median of the sample and to move the two halves of the rest of
the sample to each subarray, such that they can be used in the subarrays, without having
to be sorted again. This algorithm is called samplesort.
答:取样的位置有以下几种可能的方式(还有更多的可能方式):
1)待排序数组的左端2^k-1个元素

2)待排序数组右端2^k-1个元素

3)待排序数组中非两端的连续位置

4)随机位置的2^k-1个不重复位置的元素。

对于4)随机位置,要实现对取样元素排序后再移动到原数组无法实现,

对于3)非两端的连续位置,对现有的快速排序代码改动会比较多。

对于1,2)两端的位置,对现有快速排序代码改动少,同时满足题目要求的移动排序后的样本比较方便。

下面是代码成功运行的截图:
图片
下面是左端取样的代码实现:

public class E2d3d24v1
{
    public static void sort(Comparable[] a,int k)
    {
      sort(a,0,a.length-1,k);
    }
   
    private static void sort(Comparable[] a,int lo,int hi,int k)
    {
        if (hi<=lo) return;
        //使用快速排序对数组a的lo~hi段的左端的2^k-1个样本元素进行排序
        int sampleLen=(int)Math.pow(2,k)-1;
        //仅在待排序子数组的长度大于2^k-1时才使用取样排序,否则切换到标准的快速排序
        if (sampleLen<hi-lo+1)
        {
          //先对样本使用标准快速排序进行排序
          E2d3d24s1.sort(a,lo,lo+sampleLen);
          //取样本的中位数索引
          int midIndex=lo+sampleLen/2;
         //将样本中位数与样元集的最后一个元素进行交换,以使在后续中将中位数作为切分元素
          exch(a,lo+sampleLen-1,midIndex);
         //样本元素不参与切分,但样本的最后一个元素需要作为待切分子数组的开始元素。
          int j=partition(a,lo+sampleLen-1,hi);
         //交换样本中大于切分元素和切分数组中小于切分元素的元素。
         //从两端向中间位置的切分元素位置靠拢进行交换
         //当向右或向左指针有任意一个遇到切分元素位置时结束交换
         int i;
         for(i=midIndex;i<lo+sampleLen-1 && lo+sampleLen-1<j;i++,j--)
           exch(a,i,j);
        //结束交换分为三种情况
        //1)i,j指向切分元素,此时切分元素所在的位置mid=i=j
        //2)i未指向切分元素,j指向了切分元素,此情说明在交换前切分元素左边样本中大于切分元素的个数比其右边的小于它的元素多,此时再交换i与切分元素,使得保持切分元素左边小于切分素,切分右边大于切分元素
        //3)i指向切分元素,j未指向切分元素,此情说明在交换前切分元素左边样本中大于切分元素的个数比其右边的小于它的元素少,此时再交换j与切分元素,使得保持切分元素左边小于切分素,切分右边大于切分元素
        int mid=0;
        if(i==j)
            mid=i;
        else if(i<lo+sampleLen-1)
        {
            exch(a,i,lo+sampleLen-1);
            mid=i;
        }
        else if(lo+sampleLen-1<j)
        {
            exch(a,j,lo+sampleLen-1);
            mid=j;
        }
        sort(a,lo,mid-1,k);
        sort(a,mid+1,hi,k);
        }
        //待排序数组长度大于等于2^k-1时,使用标准快速排序
        else
        {
           int j=partition(a,lo,hi);
           //标准快速排序中的切分元素与分界元素的交换从partition中移至partition外,以便取样排序和标准快排使用相同的partition
           exch(a,lo,j);
           sort(a,lo,j-1,k);
           sort(a,j+1,hi,k);
        }
       
    }
  
    private static int partition(Comparable[] a,int lo,int hi)
    {
        int i=lo,j=hi+1;
        Comparable v=a[lo];
        while(true)
        {
            while(less(a[++i],v)) if(i==hi) break;
            while(less(v,a[--j])) if(j==lo) break;
            if(i>=j) break;
            exch(a,i,j);
        }
       // exch(a,lo,j);
        return j;
    }
   

   
    private static boolean less(Comparable v,Comparable w)
    { return v.compareTo(w)<0;}
   
    private static void exch(Comparable[] a,int i,int j)
    {
        Comparable  t=a[i];
        a[i]=a[j];
        a[j]=t;
    }
   
    private static void show(Comparable[] a)
    {
        for (int i=0;i<a.length;i++)
            StdOut.print(a[i]+" ");
        StdOut.println();
    }
   
    public static boolean isSorted(Comparable[] a)
    {
        for (int i=1;i<a.length;i++)
            if(less(a[i],a[i-1])) return false;
        return true;
    }
   
    public static void main(String[] args)
    {
        int N=Integer.parseInt(args[0]);
        int k=Integer.parseInt(args[1]);
        //
        Double[] a=new Double[N];
        for(int i=0;i<N;i++)
            a[i]=StdRandom.random();
        //
        sort(a,k);

        StdOut.println("isSorted="+isSorted(a));
    }
}
//
public class E2d3d24s1
{/*
    public static void sort(Comparable[] a,int lo,int hi)
    {
      sort(a,lo,hi);
    }
    */
    public static void sort(Comparable[] a,int lo,int hi)
    {
        if (hi<=lo) return;
        int j=partition(a,lo,hi);
   
        sort(a,lo,j-1);
        sort(a,j+1,hi);
    }
 
    private static int partition(Comparable[] a,int lo,int hi)
    {
        int i=lo,j=hi+1;
        Comparable v=a[lo];
        while(true)
        {
            while(less(a[++i],v)) if(i==hi) break;
            while(less(v,a[--j])) if(j==lo) break;
          
            if(i>=j) break;
            exch(a,i,j);
        }
        exch(a,lo,j);
        return j;
    }
   

   
    private static boolean less(Comparable v,Comparable w)
    { return v.compareTo(w)<0;}
   
    private static void exch(Comparable[] a,int i,int j)
    {
        Comparable  t=a[i];
        a[i]=a[j];
        a[j]=t;
    }
   

   
    public static boolean isSorted(Comparable[] a)
    {
        for (int i=1;i<a.length;i++)
            if(less(a[i],a[i-1])) return false;
        return true;
    }
   
    public static void main(String[] args)
    {
        int N=Integer.parseInt(args[0]);
        Double[] a=new Double[N];
        StdOut.println(a.length);
        for(int k=0;k<N;k++)
            a[k]=StdRandom.random();
        sort(a,0,a.length-1);

        StdOut.println("isSorted="+isSorted(a));
    }
}


转载于:https://www.cnblogs.com/longjin2018/p/9868579.html

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值