请务必理解这个Java代码:-)

时间:2010-05-19 20:55:12

标签: java

只是想知道是否有人能够看一下这段代码来实现quicksort算法并回答我几个问题,请: - )

public class Run
{
  /***************************************************************************
   * Quicksort code from Sedgewick 7.1, 7.2.
   **************************************************************************/
  public static void quicksort(double[] a)
  {
    //shuffle(a); // to guard against worst-case
    quicksort(a, 0, a.length - 1, 0);
  }

  static void quicksort(final double[] a, final int left, final int right, final int tdepth)
  {
    if (right <= left)
      return;
    final int i = partition(a, left, right);

    if ((tdepth < 4) && ((i - left) > 1000))
    {
      final Thread t = new Thread()
      {
        public void run()
        {
          quicksort(a, left, i - 1, tdepth + 1);
        }
      };
      t.start();
      quicksort(a, i + 1, right, tdepth + 1);

      try
      {
        t.join();
      }
      catch (InterruptedException e)
      {
        throw new RuntimeException("Cancelled", e);
      }
    } else
    {
      quicksort(a, left, i - 1, tdepth);
      quicksort(a, i + 1, right, tdepth);
    }
  }

  // partition a[left] to a[right], assumes left < right
  private static int partition(double[] a, int left, int right)
  {
    int i = left - 1;
    int j = right;
    while (true)
    {
      while (less(a[++i], a[right]))
        // find item on left to swap
        ; // a[right] acts as sentinel
      while (less(a[right], a[--j]))
        // find item on right to swap
        if (j == left)
          break; // don't go out-of-bounds
      if (i >= j)
        break; // check if pointers cross
      exch(a, i, j); // swap two elements into place
    }
    exch(a, i, right); // swap with partition element
    return i;
  }

  // is x < y ?
  private static boolean less(double x, double y)
  {
    return (x < y);
  }

  // exchange a[i] and a[j]
  private static void exch(double[] a, int i, int j)
  {
    double swap = a[i];
    a[i] = a[j];
    a[j] = swap;
  }

  // shuffle the array a[]
  private static void shuffle(double[] a)
  {
    int N = a.length;
    for (int i = 0; i < N; i++)
    {
      int r = i + (int) (Math.random() * (N - i)); // between i and N-1
      exch(a, i, r);
    }
  }

  // test client
  public static void main(String[] args)
  {
    int N = 5000000; // Integer.parseInt(args[0]);

    // generate N random real numbers between 0 and 1
    long start = System.currentTimeMillis();
    double[] a = new double[N];
    for (int i = 0; i < N; i++)
      a[i] = Math.random();
    long stop = System.currentTimeMillis();
    double elapsed = (stop - start) / 1000.0;
    System.out.println("Generating input:  " + elapsed + " seconds");

    // sort them
    start = System.currentTimeMillis();
    quicksort(a);
    stop = System.currentTimeMillis();
    elapsed = (stop - start) / 1000.0;
    System.out.println("Quicksort:   " + elapsed + " seconds");

  }
}

我的问题是:

  1. 变量tdepth的目的是什么?

  2. 这被认为是并行快速排序的“正确”实现吗?我问,因为它不使用implements Runnableextends Thread ...

  3. 如果还没有,是否可以修改此代码以使用多个线程?通过传递要用作参数的线程数,例如......?

  4. 非常感谢,

    布赖恩

4 个答案:

答案 0 :(得分:5)

1。它用于跟踪递归深度。检查这是否决定是否并行运行。注意当函数并行运行时,它如何传递tdepth + 1(在被调用的quicksort参数中变为tdepth)。这是避免太多并行线程的基本方法。

2。是的,它肯定是使用另一个线程。代码:

new Thread()
{
  public void run()
  {
    quicksort(a, left, i - 1, tdepth + 1);
  }
};

创建一个anonymous inner class(扩展Thread),然后启动它。

答案 1 :(得分:2)

  1. 显然,tdepth用于避免创建太多线程

  2. 它使用匿名类,隐式扩展Thread

  3. 它已经这样做了(见第1点。)

答案 2 :(得分:0)

  1. tdepth存在,因此创建的线程数有一个上限。请注意,随着方法递归调用自身(在新线程中完成),tdepth会递增1。这样,只有前四个级别的递归才会创建新线程,大概是为了防止用多线程重载操作系统,效果不大。

  2. 此代码在quicksort方法的定义中启动自己的线程,因此它将使用并行处理。有人可能会说,它可以通过某种线程管理来实现,例如某种Executor可能会更好,但肯定是平行的。查看对new Thread() ...的来电,然后是start()。顺便说一句,对t.join()的调用将导致当前线程等待线程t完成,以防您不知道。

    < / LI>
  3. 此代码已使用多个线程,但您可以调整在tdepth上进行比较时产生的线程数;增加或减少该值将决定递归级别创建多少级别。您可以完成重写代码以使用执行程序和线程池,或者可能执行三次递归而不是二进制 - 但我怀疑在您要求的意义上;不,没有简单的方式来调整线程数。

答案 3 :(得分:0)

我确实用Java编写了一个(正确的)多线程QuickSort,所以也许我可以帮一下......

对于任何有兴趣的人都在这里提问:

Multithreaded quicksort or mergesort

  

变量的目的是什么   tdepth?

正如其他人所评论的,它用于确定是否创建新线程。

  

这被认为是“适当的”   实现并行   快速排序?我问,因为它没有   使用实现Runnable或extends   螺纹...

我不认为这是正确的有几个原因:首先你应该让它依赖于CPU。在仅具有一个核心的CPU上产生16个线程毫无意义:单线程QuickSort将优于单核心机器上的多线程QuickSort。在16核机器上,当然可以激活16个线程。

Runtime.getRuntime().availableProcessors()

然后我真的不喜欢它的第二个原因是它使用了上世纪的低级Java特性线程细节:我更喜欢远离 .join()并使用更高版本等级事物(参见另一个问题中的fork / join或类似CountDownLatch'es等)。像Java的线程“加入”这样的低级问题是它没有任何有用的含义:这是100%Java特定的,可以被更高级别的线程设施所取代,它们的概念可以跨语言移植。

然后不要在开头评论洗牌。永远。我已经看过数据集,如果你删除那个shuffle,QuickSort会以二次方式降级。它只是一个O(n)shuffle,不会减慢你的排序:)

  

如果还没有,是否可能   修改此代码以使用多个   线程?通过传递数量   你想要用作的线程   参数,例如......?

我尝试使用更高级别的并发工具编写和/或重用实现。请查看我前一段时间提出的问题中的建议。