我的任务是使用两个堆栈a
和b
对整数堆栈a
中的数字进行升序排序。
使用十一种操作:
1.sa:swap a
-交换堆栈a
顶部的前2个元素
1.sb:swap b
-交换堆栈b
顶部的前2个元素。
1.ss:同时存在sa
和sb
。
1.pa:push a
-取b
顶部的第一个元素,并将其放在a
的顶部。
1.pb:push b
-取a
顶部的第一个元素,并将其放在b
的顶部。
1.ra:rotate a
-堆栈a
的所有元素上移1。第一个元素变为最后一个元素。
1.rb:rotate b
-堆栈b
的所有元素上移1。第一个元素变为最后一个元素。
1.rr:同时出现ra
和rb
。
1.rra:reverse rotate a
-堆栈a
中的所有元素下移1。最后一个元素变为第一个元素。
1.rrb:reverse rotate b
-堆栈b
的所有元素下移1。最后一个元素成为第一个元素。
1.rrr:同时出现rra
和rrb
。
我的排序功能
void sorts_stack(stack *a, stack *b)
{
int srt;
srt = is_not_sorted(a);
if (srt)
{
if (a->list[srt] == top(a) && a->list[srt] > a->list[0])
{
rotate_ra_rb(a->list, a->size); //ra : rotate a
putstr("ra\n");
}
else if (a->list[srt] == top(a) && a->list[srt] > a->list[srt - 1])
{
swap_sa_sb(a->list, a->size);//sa : swap a
putstr("sa\n");
}
else if (a->list[srt] > a->list[srt - 1])
{
putstr("pb\n"); //pb : push b
push_pb(a, b);
}
sorts_stack(a, b);
}
else if (b->size > 0)
{
if (top(a) < top(b))
{
push_pa(a, b); //pa : push a
putstr("pa\n");
}
else if ((top(a) > top(b)) && b->size != 0)
{
push_pa(a, b); //pa : push a
putstr("pa\n");
}
sorts_stack(a, b);
}
}
我的函数正在对堆栈进行排序,我认为排序步骤太多。我需要有关如何使它以较少的步骤对堆栈进行排序的建议或意见。complete online code
3条答案
按热度按时间v1l68za41#
给定两个栈A和B,其中A填充有元素的随机排列,B为空,并且一个临时变量T能够容纳一个元素(和一个计数器,但计数器不计数),您可以按升序将A排序到B中:
1.将所有元素从A移动到B,但保留T中的最大元素
1.将所有元素从B移动到A
1.将T中的元素放入堆栈B
1.循环直到A为空
1.将所有元素从A移动到B,但保留T中的最大元素
1.将所有元素从B移动到A,除了底部最大的元素(这里是计数器方便保存B中已排序元素数量的地方)
1.将T中的元素放入堆栈B
当然,您可以(也应该)将所有这些内容放在一个循环中。
enxuqcxy2#
原来这是42学校的学生项目挑战赛
a
和b
不是堆栈。通常将一组整数读入用于排序逻辑的数组,然后被复制到a
中。a
和b
通常被实现为循环双链表。11个允许的操作包括交换和旋转,这些操作不是本机堆栈操作。可以使用附加数组来生成一组操作,以对a
中的整数集进行排序。链接到稍后发布的同一问题的答案:
https://stackoverflow.com/a/75115367/3282056
这是我之前的回答,假设没有其他数组可以用来帮助生成一组命令,结果限制为使用11个操作中的4个来实现两个队列的合并排序。
这实际上是一个双队列问题,因为rotate操作有效地将堆栈转换为队列(push + rotate == queue push back)。在这种情况下,可以执行自底向上的合并排序,这将相对较快。
使用链表或循环(而不是线性数组)来实现堆栈/队列将加快循环。
2个队列的自下而上合并排序:
初始拆分:从原始队列中弹出元素,并将元素交替追加到原始队列和临时队列。将队列大小设置为从原始队列中弹出的元素数。将排序后的运行大小设置为1。
合并排序遍数:设置两个本地剩余队列大小变量=两个队列大小,以确定合并排序传递的结束。每次移动都会减少剩余队列大小。设置一个本地目标变量,元素最初将移动到该变量的队列(如果是最后一次传递,则设置为移动到
a
)。合并一对管路:将两个局部剩余运行大小变量设置为MIN(运行大小、剩余队列大小)。每次移动都会减少一个剩余运行大小。如果其中一个剩余运行大小为零,则移动另一个运行的剩余部分并中断,否则合并一对元素。重复此操作,直到其中一个运行大小为零。
结束合并一对管路:切换目标变量,使接下来的两次运行合并到另一个队列中。重复操作,直到剩下的两个队列大小都为零。
如果
b
的大小为零,则完成合并排序,否则将游程大小加倍并执行另一个合并排序过程。yrefmtwq3#
下面是一个Java的解决方案。