【问题标题】:Why is my quickSort method giving me a StackOverflowError? Java为什么我的 quickSort 方法给了我一个 StackOverflowError?爪哇
【发布时间】:2020-04-02 03:53:48
【问题描述】:

这是我的快速排序方法。它由两种不同的方法组成:一种将队列作为参数(1),另一种将数组作为参数(2)。然后它使用参数数组使队列被传递给(1)。

(2)

public static <E> void quickSort(
   E[] array,
   Comparator<E> comp,
   long start,
   long timeOut
) throws TimeoutException {
   Queue<E> queue = new LinkedQueue<>();

   for (int i = 0; i < array.length; i++)
   {
      queue.enqueue(array[i]);
   }

   quickSort(queue, comp, start, timeOut);

   Object[] newArray =  new Object[queue.size()];

   for ( int i = 0; i < queue.size(); i++)
   {
      newArray[i] = queue.dequeue();
   }

   if (System.currentTimeMillis() - start > timeOut)
   {
      throw new TimeoutException("Quick sort has timed out.");
   }       
}

(1)

public static <E> void quickSort(
   Queue<E> queue,
   Comparator<E> comp,
   long start,
   long timeOut
) throws TimeoutException {
   if (System.currentTimeMillis() - start > timeOut)
   {
      throw new TimeoutException("Quick sort has timed out.");
   }

   int n = queue.size();
   if (n < 2)
   {
      return;
   }

   // divide
   E pivot = queue.first();

   Queue<E> L = new LinkedQueue<>();
   Queue<E> E = new LinkedQueue<>();
   Queue<E> G = new LinkedQueue<>();

   while (!queue.isEmpty())
   {
      E element = queue.dequeue();
      int c = comp.compare(element, pivot);

      if (c < 0)
      {
         L.enqueue(element);
      }
      else if (c == 0)
      {
         E.enqueue(element);
      }
      else
      {
         G.enqueue(element);
      }
   }

   // conquer
   quickSort(L,comp,start,timeOut);
   quickSort(G,comp,start,timeOut);

   // concatenate results

   while (!L.isEmpty())
   {
      queue.enqueue(L.dequeue());
   }

   while(!E.isEmpty())
   {
      queue.enqueue(E.dequeue());
   }

   while(!G.isEmpty())
   {
      queue.enqueue(G.dequeue());
   }       
}

LinkedQueue 类:

import java.io.File;

public class LinkedQueue<E> implements Queue<E> {
    private SinglyLinkedList<E> list = new SinglyLinkedList<>();
    public LinkedQueue(){}
    public int size(){return list.size();}
    public boolean isEmpty(){return list.isEmpty();}
    public void enqueue(E element){list.addLast(element);}
    public E first(){return list.first();}
    public E dequeue(){return list.removeFirst();}
}

名称比较器:


public class NameComparator implements Comparator<Employee> {    
    public int compare(Employee a, Employee b)
    {
        String nameA = a.getName();
        String nameB = b.getName();
        int returnValue = 0;
        returnValue = nameA.compareTo(nameB);
        if (returnValue == 0)
        {
            return returnValue;
        }
        else if(returnValue == 1)
        {
            returnValue = -1;
            return returnValue;
        }
        else
        {
            returnValue = 1;
            return returnValue;
        }

    }
}

输出:

run:
Time to create unsorted array : 0 ms
Time to copy unsorted array : 0 ms
fvuvdm,xezvdfqvom,oqqoj,azhjksqjt,tburnf,mkyroq,yokgqrfsiz,mrexmktnz,dqbey,uvbipqag,
Exception in thread "main" java.lang.StackOverflowError
    at LinkedQueue.dequeue(LinkedQueue.java:29)
    at Sort.quickSort(Sort.java:256)
    at Sort.quickSort(Sort.java:276)
    at Sort.quickSort(Sort.java:276)
    at Sort.quickSort(Sort.java:276)
    at Sort.quickSort(Sort.java:276)
    at Sort.quickSort(Sort.java:276)
    at Sort.quickSort(Sort.java:276)
//this continues for many lines

C:\Users\jackm\AppData\Local\NetBeans\Cache\11.0\executor-snippets\run.xml:111: The following error occurred while executing this line:
C:\Users\jackm\AppData\Local\NetBeans\Cache\11.0\executor-snippets\run.xml:94: Java returned: 1
BUILD FAILED (total time: 0 seconds)

我不知道为什么会这样。

【问题讨论】:

  • 你能提供LinkedQueue类吗?
  • 如果您的比较器有问题,就会发生这种情况。它是自定义比较器吗?可以分享一下代码吗?
  • 用所有冗余代码成为你令人难以置信的比较器,你可以用return a.getName().compareTo(b.getName());替换整个身体。
  • 刚刚添加了比较器类。另外,那是我的 LinkedQueue 类。它只是实现了 SinglyLinkedList,如果需要,我也可以发布它。而LinkedQueue.first() 不会从队列中移除元素,只会返回元素。
  • 刚刚注意到您的比较器是从后到前的。为什么?

标签: java sorting recursion


【解决方案1】:

我认为你的问题出在你的比较器上。

考虑这个表达式:

"dog".compareTo("and")

它将返回 3。但您的比较器仅测试 0 和 1。当我认为您真的希望它采用 returnValue == 1 情况时,它将进入 else 情况。

由于您的比较器大部分时间返回 1,因此您从队列中提取的大多数项目最终都会进入 G,并且对 quickSort 的嵌套调用次数将与你的输入数组。 (请注意,在您的堆栈跟踪中,对quickSort 的大多数调用都来自同一行,这可能是对G 进行排序的那一行。)因此,如果您的数组中的项目数很大,则可能会产生您看到的 StackOverflowError。

您似乎希望比较器反转字符串的排序顺序。你应该只使用:

return -a.getName().compareTo(b.getName())

return b.getName().compareTo(a.getName())

【讨论】:

  • 正是如此。未指定 Comparable.compareTo() 准确返回 {-1,0,1},仅返回 {&lt;0,0,&gt;0}
猜你喜欢
  • 2015-04-23
  • 2016-03-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-05
相关资源
最近更新 更多