【问题标题】:About Sorting Algorithms applied to Stacks and Queues关于应用于堆栈和队列的排序算法
【发布时间】:2011-03-03 00:15:39
【问题描述】:

我想知道为什么我们总是对列表和数组使用诸如(插入排序或合并排序,...)之类的排序算法?为什么我们不将这些算法用于堆栈或队列?

【问题讨论】:

  • 您的问题真的是关于堆栈和队列,还是关于排序算法是否对“其他事物”有用?
  • 我想知道排序算法有利于对堆栈和队列等其他数据结构进行排序......?

标签: java data-structures


【解决方案1】:

堆栈和队列是抽象的数据类型,它们有自己的顺序感,即堆栈的 LIFO(后进先出)和队列的 FIFO(先进先出)。因此,获取队列/堆栈并重新排列它们的元素是没有意义的。

维基百科参考


堆栈与向量

您可能会注意到,在 Java 中,java.util.Stackextendsjava.util.Vector,因为对 Vector 进行排序是有意义的,所以对 Stack 进行排序可能也有意义。然而,情况并非如此; Stack extends Vector 实际上是一个设计错误。堆栈不是向量。

相关问题


java.util.Stack 上使用 Collections.sort

尽管在堆栈上使用快速排序没有意义,但您可以实际上在 java.util.Stack 上使用 Collections.sort。为什么?因为,由于设计错误(这一点怎么强调都不为过!),java.util.Stack 就是java.util.Vector,而implements java.util.List,你肯定可以排序List。这是一个例子:

    Stack<Integer> stack = new Stack<Integer>();
    stack.push(1);
    stack.push(3);
    stack.push(5);
    stack.push(2);
    stack.push(4);

    Collections.sort(stack); // by virtue of design error!!!

    System.out.println(stack); // prints "[1, 2, 3, 4, 5]"
    while (!stack.isEmpty()) {
        System.out.println(stack.pop());
    } // prints "5", "4", "3", "2", "1"

请注意,元素是按降序打印的:这是因为java.util.Stack 的实现方式。它从Vector 的末尾推送和弹出。你不需要知道这一点;你不应该知道这一点;但这些都是事实。


关于使用适当的数据结构

根据您要完成的任务,TreeSet 可能是合适的数据结构。它是Set,所以它不允许重复元素。

    NavigableSet<Integer> nums = new TreeSet<Integer>();
    nums.add(5);
    nums.add(3);
    nums.add(1);
    nums.add(2);
    nums.add(6);

    System.out.println(nums.pollFirst()); // prints "1"
    System.out.println(nums.pollFirst()); // prints "2"
    nums.add(4);
    System.out.println(nums.pollFirst()); // prints "3"
    System.out.println(nums.pollFirst()); // prints "4"

【讨论】:

  • 考虑这个堆栈 A =(2,7,3,9,1,5) 为什么像 A=(1,2,3,5,7, 9)??
  • 因为在堆栈上,当您弹出一个元素时,您希望获得最后一个推送的元素。但是在你的例子中(假设推入的元素放在开头)在推入 2 然后排序之后,你会在弹出时得到 1。
  • @matin1234:你当然可以从堆栈的元素中创建一个List,然后按照你的意愿重新排列它们。然而,对堆栈本身的元素重新排序,违反了堆栈是什么以及它应该如何表现的定义。
  • 堆栈扩展向量不是问题。从 Vector 继承的额外功能不允许你做任何你不能通过一系列弹出和推送(包括排序)做的事情。与无休止的“是圆是椭圆”的争论形成对比。
  • @matin1234:不,你不会“有时”这样做。由于设计错误,您可以这样做。你不应该这样做。这里有很多问题需要消化,但最终的事实是堆栈不应该是可排序的。您可以以一种或另一种方式做到这一点,但此时您确实在滥用堆栈。
【解决方案2】:

这是因为堆栈或队列的顺序是这些数据结构定义的一部分。如果我们对它们进行排序,它们就不会是堆栈或队列。

【讨论】:

  • 好的,但我可以保存它们的顺序(FIFO 和 LIFO),并可以用 2 个以上的堆栈或队列对它们进行排序吗?
  • 我不确定我是否关注你,但无论如何:对堆栈进行排序没有意义,因为它的顺序很重要。
【解决方案3】:

正如其他人所指出的,通常对堆栈和队列进行排序是没有意义的。只是为了让图片完整,有一个例外:PriorityQueue,它保持其元素有序。

【讨论】:

    【解决方案4】:

    堆栈或队列是不同于序列的概念。数组和链表代表序列,您可以将它们视为已排序或未排序。

    【讨论】:

      【解决方案5】:

      堆栈和队列有自己独特的结构。 堆栈是一种应用后进先出(LIFO)的结构。如果您订购了一个堆栈,那么它将违反 LIFO。 认为我将 7、3、5、4 添加到堆栈中。 如您所知,堆栈只能检索最后添加的元素。每当我们调用 pop() 方法时,它都会检索 4。 但是,请考虑您现在对其进行排序。它变成 3, 4, 5, 7,当我们 pop() 时,它将检索 7,这是我们添加的第一个元素。这违反了 LIFO 规则。

      同样适用于队列,因为队列结构适用先进先出。如果您有任何问题,请不要犹豫。

      【讨论】:

        【解决方案6】:

        首先堆栈和队列也是列表,但有一些特殊的特性。由于它们是列表,因此您始终可以对它们进行排序,但如果这样做,您可能会更改这些数据结构的属性。

        那么在整个代码中使用这些数据结构并在某些时候对它们进行排序以释放我们使用它们的属性将毫无意义。

        【讨论】:

          猜你喜欢
          • 2014-07-21
          • 2011-11-20
          • 2021-11-02
          • 1970-01-01
          • 2017-01-17
          • 1970-01-01
          • 1970-01-01
          • 2013-06-19
          • 2013-09-18
          相关资源
          最近更新 更多