按升序对堆栈进行排序?(仅使用 3 个堆栈)

Sorting a stack in ascending order? (using only 3 stacks)

本文关键字:堆栈 升序 排序      更新时间:2023-10-16

所以我正在为 CompSci 2 做一些功课,作业要求我们使用 3 个堆栈按升序对单个堆栈(五个数字)进行排序 - 很像河内塔问题 - 但没有关于是否可以将较大的数字放在较小的数字上等的规则。

我本质上是在尝试找出一个关于如何将任何数字与堆栈中的另一个数字进行排序的过程,但我有点不知所措 - 在尝试制定一个想法时,我想出了这个:我可以从堆栈中弹出顶部数字,将其放在另一个堆栈中(例如,堆栈 3),将其与原始堆栈中的下一个数字进行比较, 如果它小于它,我会将堆栈 3 中的数字放入堆栈 2。 但后来我遇到了顺序问题——如果数字小于它后面的数字,但不小于堆栈中的另一个数字,我的最终结果将是无序的。

有人可以在这里帮助我找出最有效的方法吗?

我建议将堆栈 1 和 2 一起使用作为可遍历列表,然后使用堆栈 3 作为临时持有应用气泡排序。

我也支持基于插入排序的,但我发现@Beta的答案有点令人困惑,所以我自己工作,写成伪代码。

我们将这三个堆栈命名为 sourcetempresult 。他们的顶级项目分别为*source*temp*result

我们将尝试使result堆栈始终按底部最大的项目和顶部最小的项目进行排序。

While `source` isn't empty we:
    While `*source` is bigger than `*result`
        put `*result` onto `temp`.
    put `*source` onto `result`.
    Put all the items from `temp` back onto `result`.

我会做一个插入排序。堆栈 1 是原始的未排序数字,堆栈 2 按升序排列(最后插入的元素最大),堆栈 3 按降序排列,堆栈 3 中的最小元素(位于顶部)大于堆栈 2 中的最大元素(也在顶部)。

这种方法和@AMADANONinc.一样,不需要状态或其他变量的记忆,我认为它更快。

将 1、2 和 3 的顶部元素分别称为"A"、"B"和"C"。

编辑:我已经重写了算法,我认为它现在很严格。按顺序尝试这些规则,当您移动元素时,请返回到开头。

  1. 如果堆栈 1 和堆栈 3 都是空的,那么我们就完成了。
  2. 如果堆栈 1 为空(但 3 不是),则将 C 移动到堆栈 2。
  3. 如果 B 大于 A,请将 B 移动到堆栈 3。
  4. 如果 C 小于 A,则将 C 移动到堆栈 2。
  5. (由于前面的规则都不适用)将 A 移动到堆栈 2 或堆栈 3。

例如,假设堆栈 1 以 {22,44,11,55,33} 开头(33 位于顶部)。根据规则5,将33移至2。根据第5条,将55移至2。根据规则 3,将 55 移至 3。根据规则 3,将 33 移至 3。根据规则5,将11移至2。根据规则4,将33移至2。根据规则5,将44移至3。根据规则 3,将 33 移至 3。根据规则 5,将 22 移至 2。根据规则2,将第33、44和55移至2。根据规则1,停止。

3 堆栈排序的最快方法是多相合并排序。只有 5 个数字,而 5 是一个多相友好的斐波那契数这一事实有所帮助。假设堆栈是 A、B、C,并且 5 个数字最初在 A 上。对于此示例,数字以相反的顺序开始。在下图中,堆栈的前面(第一个元素)位于左侧。竖线表示运行边界。注释是指要执行的下一步。注释合并意味着将两个堆栈中的 1 个运行合并到第三个堆栈。

A            B            C
|5|4|3|2|1|                             pop/push 2 from A to B        
|3|2|1|      |4|5|                      merge A + B to C ascending
|2|1|        |5|         |4 3|          merge A + B to C descending
|1|                      |2 5|4 3|      merge A + C to B ascending
             |5 2 1|     |4 3|          merge B + C to A descending
|1 2 3 4 5|                             done

移动总数(弹出/推送)= 14。

3 个堆栈的通用多相合并排序有些复杂。首先将元素从 A 移动到 B 和 C(如果元素数不是斐波那契数,则为 C),然后确定第一次合并是升序还是降序(之后它们交替),并跟踪运行大小的变化。如果有人感兴趣,我可以发布示例代码。