在C中使用两个堆栈按升序对堆栈排序

gab6jxml  于 2023-01-16  发布在  其他
关注(0)|答案(3)|浏览(120)

我的任务是使用两个堆栈ab对整数堆栈a中的数字进行升序排序。
使用十一种操作:
1.saswap a-交换堆栈a顶部的前2个元素
1.sbswap b-交换堆栈b顶部的前2个元素。
1.ss:同时存在sasb
1.papush a-取b顶部的第一个元素,并将其放在a的顶部。
1.pbpush b-取a顶部的第一个元素,并将其放在b的顶部。
1.rarotate a-堆栈a的所有元素上移1。第一个元素变为最后一个元素。
1.rbrotate b-堆栈b的所有元素上移1。第一个元素变为最后一个元素。
1.rr:同时出现rarb
1.rra:reverse rotate a-堆栈a中的所有元素下移1。最后一个元素变为第一个元素。
1.rrb:reverse rotate b-堆栈b的所有元素下移1。最后一个元素成为第一个元素。
1.rrr:同时出现rrarrb
我的排序功能

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

v1l68za4

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
当然,您可以(也应该)将所有这些内容放在一个循环中。

enxuqcxy

enxuqcxy2#

原来这是42学校的学生项目挑战赛ab不是堆栈。通常将一组整数读入用于排序逻辑的数组,然后被复制到a中。ab通常被实现为循环双链表。11个允许的操作包括交换和旋转,这些操作不是本机堆栈操作。可以使用附加数组来生成一组操作,以对a中的整数集进行排序。
链接到稍后发布的同一问题的答案:
https://stackoverflow.com/a/75115367/3282056
这是我之前的回答,假设没有其他数组可以用来帮助生成一组命令,结果限制为使用11个操作中的4个来实现两个队列的合并排序。
这实际上是一个双队列问题,因为rotate操作有效地将堆栈转换为队列(push + rotate == queue push back)。在这种情况下,可以执行自底向上的合并排序,这将相对较快。
使用链表或循环(而不是线性数组)来实现堆栈/队列将加快循环。
2个队列的自下而上合并排序:
初始拆分:从原始队列中弹出元素,并将元素交替追加到原始队列和临时队列。将队列大小设置为从原始队列中弹出的元素数。将排序后的运行大小设置为1。
合并排序遍数:设置两个本地剩余队列大小变量=两个队列大小,以确定合并排序传递的结束。每次移动都会减少剩余队列大小。设置一个本地目标变量,元素最初将移动到该变量的队列(如果是最后一次传递,则设置为移动到a)。
合并一对管路:将两个局部剩余运行大小变量设置为MIN(运行大小、剩余队列大小)。每次移动都会减少一个剩余运行大小。如果其中一个剩余运行大小为零,则移动另一个运行的剩余部分并中断,否则合并一对元素。重复此操作,直到其中一个运行大小为零。
结束合并一对管路:切换目标变量,使接下来的两次运行合并到另一个队列中。重复操作,直到剩下的两个队列大小都为零。
如果b的大小为零,则完成合并排序,否则将游程大小加倍并执行另一个合并排序过程。

yrefmtwq

yrefmtwq3#

下面是一个Java的解决方案。

public class SortStack {

    Stack<Integer> stack1;
    Stack<Integer> stack2;    

    public Stack<Integer> sort(Stack<Integer> stack) {
        this.stack1 = stack;
        stack2 = new Stack<>();
        putSmallestAtBottom();
        empty2BackTo1();
        return stack1;
    }

    private void putSmallestAtBottom() {
        /*Pop a number from stack1
        * Compare it top item in stack2
        * If stack2 item is bigger, move it stack1
        * Keep doing this
        * Once thats done push that smaller num to stack 2
        * Keep repeating until stack 1 is empty*/
        while (stack1.isEmpty() == false) {
            int num = stack1.pop();
            while (stack2.isEmpty() == false && stack2.peek() > num) {
                stack1.push(stack2.pop());
            }
            stack2.push(num);
        }
    }

    private void empty2BackTo1() {
        while (stack2.isEmpty() == false) {
            stack1.push(stack2.pop());
        }
    }    
}

相关问题