双栈算法(一)

1、设计一个有getMin功能的栈,除了实现栈基本的功能外,再实现返回栈中最小元素的操作。

  • pop,push,getMin操作的时间复杂度均为O(1)
  • 可使用现成的栈结构

思想:在实现时使用两个栈,一个栈记录当前的数据,另一个栈保存当前的最小值。有两种实现方式,现实现第一种:

(1)压入数据规则:

​ 新元素为newData,先将newData压入data栈中,然后进行判断,如果min栈也为空,则将newData压入min栈中。如果不为空,比较newData和min栈的栈顶元素的大小,如果newData <= min.top(), 则将newData压入min栈中,否则不进行操作。

(2)弹出数据规则:

​ 先弹出data栈的栈顶元素,记为value,然后与min栈的栈顶元素进行比较,如果value == min.top(), min栈弹出栈顶元素;当value > min.top()时,返回value。

​ 不难得出min栈中的元素是从栈底到栈顶逐渐变小的,min栈栈顶的元素是min栈的最小值,也是当前data栈的最小值,所以value值只可能>=min.top()

(3)查询当前栈中最小值

​ 直接返回min栈的栈顶元素,当为空时直接推出。

代码:

class mystack
{
public:
    mystack() {
        cout << "mystack()" << endl;
    }
    ~mystack() {
        cout << "~mystack()" << endl;
    }
    int getMinData() const {
        if (stackMin.empty()) {
            cout << "your stackMin is empty" << endl;
            return 0;
        }
        return stackMin.top();
    }
    void push(const int newData) {
        stackData.push(newData);
        if (stackMin.empty()) {
            stackMin.push(newData);
        }
        else {
            auto temp = stackMin.top();
            if (newData <= temp) {
                stackMin.push(newData);
            }
        }
    }

    int pop() {
        auto temp = stackData.top();
        stackData.pop();
        if (temp == stackMin.top()) {
            stackMin.pop();
            return temp;
        }
        if (temp > stackMin.top()) {
            return temp;
        }
    }

private:
    stack<int> stackData;
    stack<int> stackMin;
};

2、通过两个栈实现队列

思想:定义两个栈stPush, stPop,压入数据时只往stPush中压入,弹出数据时只从stPop中弹出,这样就能实现类似队列的功能。但是有两个注意事项:

  • 如果要从stPush往stPop中压入数据,必须一次性把所有数据全部压入。
  • 如果stPop不为空,则不能向其中压入数据。

代码:

class stackQueue {
public:
    stackQueue() { cout << "stackQueue()" << endl; }
    ~stackQueue() { cout << "~stackQueue()" << endl; }
    void add(const int newNum) {
        stPush.push(newNum);
        if (stPop.empty()) { pushToPop(); }
    }

    int pop() {
        if (stPush.empty() && stPop.empty()) {
            cout << "stackQueue is empty" << endl;
            return -1;
        }
        pushToPop();
        auto temp = stPop.top();
        stPop.pop();
        return temp;
    }

    int front() {
        if (stPush.empty() && stPop.empty()) {
            cout << "stackQueue is empty" << endl;
            return -1;
        }
        pushToPop();
        return stPop.top();
    }


private:
    stack<int> stPush;
    stack<int> stPop;
    void pushToPop() {
        if (stPop.empty()) {
            while (!stPush.empty()) {
                auto temp = stPush.top();
                stPop.push(temp);
                stPush.pop();
            }
        }
    }
};
01-03 20:14