Как я могу логически инвертировать стек методом, который работает в O (1)?

#data-structures #stack #big-o

#структуры данных #стек #big-o

Вопрос:

Я написал следующий код стека:

 #include <iostream>
using namespace std;

template <typename T>
class Stack 
{
    T *sptr;
    int cap;
    int top;
    
public:
    Stack ()
    {
        sptr = nullptr;
        top = -1;
        cap = 0;
    }
    
    void push (const Tamp; obj)
    {
        if (top == -1)
        {
            sptr = new T[1];
            cap = 1;
            sptr[  top] = obj;
        }
        else if (cap == (top   1))
        {
            cap *= 2;
            T *temp = new T[cap];
            for (int i = 0; i <= top; i  )
                temp[i] = sptr[i];
            temp[  top] = obj;
            delete [] sptr;
            sptr = temp;
            temp = nullptr;
        }
        else
        {
            sptr[  top] = obj;
        }
    }
    
    inline bool empty () const
    {
        return (top == -1);
    }
    
    inline int size () const
    {
        return (top   1);
    }
    
    const Tamp; peek () 
    {
        return sptr[top];
    }
    
    void pop ()
    {
        if (top >= 0)
        {
            if (top == 0)
            {
                top = -1;
                cap = 0;
                delete [] sptr;
            }
            else if (top >= (cap/2 -1))
            {
                top--;
            }
            else
            {
                cap /= 2;
                T *temp = new T [cap];
                for (int i = 0; i < top; i  )
                {
                    temp[i] = sptr[i];
                }
                delete [] sptr;
                sptr = temp;
                temp = nullptr;
                top--;
            }
        }
    }
    
    /*void flip() // flip method
    {
        
    }*/
};
  

Теперь я хочу реализовать метод flip, который логически инвертирует стек таким образом, что самый старый элемент становится самым новым элементом, поэтому следующий pop удалит элемент, который был в нижней части стека до того, как он был перевернут. И я должен иметь возможность снова и снова переворачивать в O (1).

Ответ №1:

Невозможно перевернуть реальный стек в O (1).

Лучшее, что вы можете сделать, это O (n) . Чтобы увидеть это, вам нужно только заметить, что для получения нижнего элемента стека вам нужно вставить его n раз.

Тем не менее, вы можете сделать это в O (n):

Что вы можете сделать, чтобы создать еще один стек, вытащить содержимое, нажав на другой. Когда оригинал пуст, отбросьте его и верните новый стек.

ОБНОВЛЕНИЕ: однако ваша реализация поддерживается массивом, который строго более мощный, чем стек.

Вы можете изменить его, сохранив флаг направления, и когда запрашивается revese для переключения головы в хвост, изменения флага, а также направления обхода. Также будет некоторая дополнительная бухгалтерия для управления памятью, поскольку вам, возможно, придется расширять как high, так и low.

Я предлагаю создать чертеж структуры данных, чтобы вы могли отслеживать, что происходит со смещениями.

Для аналогичной, но фиксированной структуры размера вы можете взглянуть на это: https://www.codeproject.com/Articles/3479/The-Bip-Buffer-The-Circular-Buffer-with-a-Twist

Комментарии:

1. Будет ли это работать в O (1), как спрашивает OP? Я думаю, что это O (n) .

Ответ №2:

Что вам нужно, так это Deque, который позволяет добавлять и удалять элементы с обоих концов:

https://en.wikipedia.org/wiki/Double-ended_queue

Чтобы использовать его как обратимый стек, вы просто сохраняете логическую переменную, чтобы определить, с каким концом будут работать операции стека.