【问题标题】:Generic arraylist bubblesort problems通用数组列表冒泡排序问题
【发布时间】:2013-10-05 17:52:01
【问题描述】:

我知道有内置的例程,但作为一个学习者,我想使用自己的设备进行排序,而且由于排序是旧帽子,我决定尝试制作自己的通用排序例程如果我弄清楚它们在 Java 中是如何工作的,我可以使用数字或字符串,甚至日期。

这就是我所拥有的,直到现在我只在两个地方(包含在“**”标记内)有错误,需要弄清楚如何比较。

package sort;
import java.util.ArrayList;

public  abstract class Sort<E> implements Comparable<E> {

   public void swap(ArrayList<E> a, int i, int j) {
    E c = a.get(i);
    a.set(i,a.get(j));// = a[j];
    a.set(j, c);
  }

  public void bubbleSort(ArrayList<E> a) {
    boolean inOrder = false;
    while (!inOrder) {
      inOrder = true;
      for (int i = 1; i < a.size(); i++) {
        **if( a.get(i - 1).compareTo(a.get(i)) > 0 )** {
//cannot find symbol: method compareTo(E); location: class Object
//where E is a type-variable: E extends Object declared in class Sort                 
      inOrder = false;
          swap(a, i, i - 1);
        } 
      }
    }
  }

  public static void main(String args[]) //hadda lose 'static' for 'setLayout' to work
  {
    ArrayList<Integer> ary = new ArrayList<>();
    ary.add(2); ary.add(4); ary.add(7); ary.add(3);
    **bubbleSort(ary)**;
//method bubbleSort in class Sort<E> cannot be applied to given types; 
//required: ArrayList<E>
//found: ArrayList<Integer>
//reason: actual argument ArrayList<Integer> cannot be converted to ArrayList<E> 
//by method invocation conversion where E is a type-variable:
//E extends Object declared in class Sort
    for (int i = 0; i < ary.size(); i++) {
      System.out.println(ary.get(i));
    }
  }

  @Override
  public int compareTo(E o) {
    **return 0;** // fixing errors above may help this fall into place
  }
}

我正在尝试学习我感觉准备好的东西,却发现我还没有完全准备好;关闭,无雪茄。

【问题讨论】:

  • 我可以建议,作为一个学习者,你学习的排序算法比冒泡排序更好吗?
  • 另外,如果bubbleSort() 是一个实例方法,你可能想要new Sort&lt;Integer&gt;().bubbleSort(ary); 如果它是一个静态方法,你需要在方法本身上显式地传递类型参数,通过声明方法为public static &lt;E extends Comparable&lt;E&gt;&gt; bubbleSort(ArrayList&lt;E&gt; a) {...},而不是将类型参数放在Sort 类上,在这种情况下它只充当命名空间。
  • 你完全误解了泛型。
  • 我完全不知道为什么Sort implements Comparable。你可能打算让E 有界docs.oracle.com/javase/tutorial/java/generics/bounded.html
  • 我还可以建议您不要对集合进行排序,而是对数组进行排序?您选择了计算机科学已知的最低效的排序算法之一,并且以最糟糕的方式应用它。

标签: java generics arraylist


【解决方案1】:

这个:

public  abstract class Sort<E> implements Comparable<E> {

表示E 是任意对象类型,Sort&lt;E&gt; 的实例可以与E 的实例进行比较。 (所以你的错误信息是抱怨E.compareTo 不存在,因为Object 没有这样的方法。)你想要的是这个:

public abstract class Sort<E extends Comparable<E>> {

这意味着E 必须是其实例可以相互比较的类型。


编辑添加:实际上,正如 SLaks 共同指出的那样,Sort 没有真正的理由是通用的;你只需要bubbleSort 方法是通用的。此外,正如 MadProgrammer 暗示的那样,Sort 应该是非abstract(因此您可以直接实例化它)或bubbleSort 应该是static(因此可以在不实例化Sort 实例的情况下调用它)或两者兼而有之.例如:

public class Sort {
    private static <E> void swap(ArrayList<E> a, int i, int j) {
        ...
    }

    private static <E extends Comparable<E>> void bubbleSort(ArrayList<E> a) {
        ...
    }

    ...
}

更好的是,Sort 可以是带有sort 方法的接口,而BubbleSort.sort(...) 只是它的一个实现(而不是给Sort 一个特定的bubbleSort 方法)。

【讨论】:

  • 评论最后一个问题,**bubbleSort(ary)**;,你会得到一个完整的答案;)
  • 其实这个类根本不应该是泛型的。
【解决方案2】:

如果可以的话,我想发表评论。

学习 BubbleSort 是学习如何在 Java 中使用数据结构的好方法。我同意其他人的观点,即在现实世界中,您永远不会使用 BubbleSort,因为它提供的所有排序算法中性能最差,“StoogeSort”除外。

不过,作为一个新学习者,如果它教你如何做重要的事情,如使用和应用泛型类型参数、使用控制流语句(例如 for 循环),甚至做异常处理。不要听那些反对者的话。冒泡排序的主要优点是算法简单。

在我看来,更简单的排序算法是“延迟替换排序”,也称为“选择排序”。延迟替换排序与 BubbleSort (O(n^2)) 具有相同的时间复杂度,但与 BubbleSort 不同的是,选择排序仍在某些应用程序中使用。它作为子算法被合并到一些优化的排序算法中,并且因为它最大限度地减少了排序集合所需的交换次数,所以当执行交换的成本很高时仍然使用选择排序。

延迟替换排序的伪代码如下,在我看来,它甚至比冒泡排序更简单:

Begin DELAYEDSORT
 For ITEM=1 to maximum number of items in list-1
    LOWEST=ITEM
    For N=ITEM+1 to maximum number of items in list
       Is entry at position N lower than entry at position LOWEST?
          If so, LOWEST=N
    Next N
    Is ITEM different from LOWEST
       If so, swap entry at LOWEST with entry in ITEM
 Next ITEM
End DELAYEDSORT

延迟替换排序可以比冒泡排序快 50%,但仍不应用于对非常大的集合进行排序。

【讨论】:

  • scottb 是正确的——作为 Java 的学习者(不是最优排序),bubblesort 确实帮助我克服了可能出现的大量错误;现在他让我想使用他的 p 代码或者可能实现快速排序,因为递归非常酷。 (也很酷:它的动画位于 en.wikipedia.org/wiki/Quicksort)
  • @DSlomer64:查看维基百科上“Stooge Sort”的动画。太吵了。
  • @scottb--你注意到了吗:“算法得名于三个傀儡的闹剧例程,其中每个傀儡都会击中其他两个。[需要引用]”我想知道是否所需的引用将是确认例程命名的原因,或者确认确实存在这样一集,其中 Moe 打了 Larry 和 Curly,Larry 打了 Moe 和 Curly,Curly 打了 Larry 和 Moe,如果是这样,按标题还是什么? (我想存在多个这样的情节。)
【解决方案3】:

在接受了 SLaks 的建议并更加熟悉泛型(昨天制作了泛型堆栈和队列类)之后,今天我使用了 ruakh 的大纲(但必须在“bubblesort”行中将private 更改为public)启用主要将main 更改为理智的东西(现在归结为一条有用的行Sort.bubbleSort(ary);)并且它有效,但我有两个亟待解决的问题

(1) 这行中的第一个&lt;E&gt; 究竟是什么意思/做/暗示:

private static <E> void swap(ArrayList<E> a, int i, int j) {

(2) 同样...这里的&lt;E extends Comparable&lt;E&gt;&gt; 是怎么回事:

private static <E extends Comparable<E>> void bubbleSort(ArrayList<E> a) {

回答我自己的问题,“现在,我为什么没有想到这些?”...“为什么我想到它们??”

编辑:“参数化”或“通用”方法与参数化/通用类型一样合法,为什么不呢?

但我仍然不知道为什么,“显然合法”与否,我会想到任何一个“技巧”。

编辑:一个字:经验

【讨论】:

    猜你喜欢
    • 2020-12-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-15
    • 2015-01-02
    • 2016-02-10
    相关资源
    最近更新 更多