《算法导论》笔记 第10章 10.1 栈和队列

【笔记】

栈:后进先出 LIFO

队列:先进先出 FIFO

template<typename ITEM>
class stack {
private:
    ITEM S[MAXN];
    int tp;
public:
    stack() {
        tp = 0;
    }
    bool empty() {
        return tp == 0;
    }
    void push(ITEM x) {
        if (tp == MAXN) throw "stack overflow";
        S[tp++] = x;
    }
    ITEM top() {
        if (tp == 0) throw "stack empty";
        return S[tp-1];
    }
    void pop() {
        if (tp == 0) throw "stack underflow";
        tp--;
    }
    int size() {
        return tp;
    }
};

template<typename ITEM>
class queue {
private:
    ITEM Q[MAXN];
    int head,tail;
    int sz;
public:
    queue() {
        head = tail = sz = 0;
    }
    bool empty() {
        return sz == 0;
    }
    void push(ITEM x) {
        if (sz == MAXN) throw "queue overflow";
        Q[tail++] = x;
        sz++;
        if (tail == MAXN) tail = 0;
    }
    ITEM front() {
        if (sz == 0) throw "queue empty";
        return Q[head];
    }
    void pop() {
        if (sz == 0) throw "queue underflow";
        head++;
        sz--;
        if (head == MAXN) head = 0;
    }
    int size() {
        return sz;
    }
};


【练习】

10.1-1 说明对一个储存在数组S[1..6]中的、初始为空的栈S,依次执行PUSH(S,4),PUSH(S,1),PUSH(S,3),POP(S),PUSH(S,8)以及POP(S)操作后的结果。

4 1 3

4 1

4 1 8

POP返回3


10.1-2 说明如何用一个数组A[1..n]来实现两个栈,使得两个栈中的元素总数不到n时,两者都不会发生上溢。注意PUSH和POP操作的时间应为O(1)。

两个栈分别用A[1]和A[n]做栈底,PUSH操作时,向中间插入元素,当两个栈元素总数为n时数组满,发生上溢。


10.1-3 说明对一个存储在数组Q[1..6]中的、初始为空的队列Q,依次执行ENQUEUE(Q,4),ENQUEUE(Q,1),ENQUEUE(Q,3),DEQUEUE(Q),ENQUEUE(Q,8)以及DEQUEUE(Q)操作后的结果。

4

4 1

4 1 3

1 3

1 3 8

DEQUEUE(Q)返回4


10.1-4 重写ENQUEUE和DEQUEUE,使之能处理队列的下溢和上溢。

见代码。


10.1-5 栈的插入和删除操作都是在一端进行的,而队列的插入和删除确是在两头进行的。另有一种双端队列,其两端都可以做插入和删除操作。对于一个用数组构造的双端队列,请写出四个在两端进行插入和删除操作的过程,要求运行时间都为O(1)。

template <typename ITEM>
class deque {
private:
    ITEM D[MAXN];
    int head,tail;
    int sz;
public:
    deque() {
        head = tail = 0;
        sz = 0;
    }
    bool empty() {
        return sz == 0;
    }
    ITEM front() {
        if (sz == 0) throw "deque empty";
        return D[head];
    }
    ITEM back() {
        if (sz == 0) throw "deque empty";
        return D[tail-1];
    }
    void push_front(ITEM x) {
        if (sz == MAXN) throw "deque overflow";
        if (head == 0) head = MAXN;
        head--;
        sz++;
        D[head] = x;
    }
    void push_back(ITEM x) {
        if (sz == MAXN) throw "deque overflow";
        D[tail++] = x;
        sz++;
        if (tail == MAXN) tail = 0;
    }
    void pop_front() {
        if (sz == 0) throw "deque underflow";
        head++;
        if (head == MAXN) head = 0;
        sz--;
    }
    void pop_back() {
        if (sz == 0) throw "deque underflow";
        if (tail == 0) tail = MAXN;
        tail--;
        sz--;
    }
    int size() {
        return sz;
    }
};


10.1-6 说明如何用两个栈来实现一个队列,并分析有关队列操作的运行时间。

template <typename ITEM>
class queuebytwostack{
private:
    stack<ITEM> stkin;
    stack<ITEM> stkout;
    void readyToPop() {
        while (!stkin.empty()) {
            stkout.push(stkin.top());
            stkin.pop();
        }
    }
public:
    bool empty() {
        if (stkin.empty()&&stkout.empty()) return true;
        return false;
    }
    void push(ITEM x){
        try {
            stkin.push(x);
        }
        catch (const char *e) {
            throw e;
        }
    }
    ITEM front() {
        try {
            if (stkout.empty()) readyToPop();
            return stkout.top();
        }
        catch (const char *e) {
            throw e;
        }
    }
    void pop() {
        try {
            if (stkout.empty()) readyToPop();
            stkout.pop();
        }
        catch (const char *e) {
            throw e;
        }
    }
    int size() {
        return stkin.size()+stkout.size();
    }
};
PUSH O(1)

POP O(n)


10.1-7 说明如何用两个队列来实现一个栈,并分析有关栈操作的运行时间。

template <typename ITEM>
class stackbytwoqueue {
private:
    queue<ITEM> que[2];
    int p;
public:
    stackbytwoqueue() {
        p = 0;
    }
    bool empty() {
        if (que[0].empty()&&que[1].empty()) return true;
        return false;
    }
    void push(ITEM x) {
        try {
            que[p].push(x);
        }
        catch (const char *e) {
            throw e;
        }
    }
    ITEM top() {
        try {
            int sz = que[p].size();
            ITEM res;
            for (int i=1;i<=sz;i++) {
                if (i==sz) res = que[p].front();
                que[p^1].push(que[p].front());
                que[p].pop();
            }
            p^=1;
            return res;
        }
        catch (const char *e) {
            throw e;
        }
    }
    void pop() {
        try {
            int sz = que[p].size();
            for (int i=1;i<=sz-1;i++) {
                que[p^1].push(que[p].front());
                que[p].pop();
            }
            que[p].pop();
            p^=1;
        }
        catch (const char *e) {
            throw e;
        }
    }
    int size() {
        return que[p].size()+que[p^1].size();
    }
};
PUSH O(1)

POP O(n)



原文地址:https://www.cnblogs.com/cyendra/p/3681505.html