『アルゴリズム導論』ノート第10章10.1スタックとキュー

5617 ワード

【メモ】


スタック:後進先出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は、2つのスタックの要素の合計数がn未満の場合、両方ともオーバーフローしないように、1つの配列A[1..n]で2つのスタックを実現する方法を説明する.注意PUSHとPOPの操作時間はO(1)であること.
2つのスタックはそれぞれA[1]とA[n]でスタックの底を作り,PUSH操作時には中間に要素を挿入し,2つのスタック要素の総数が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スタックの挿入と削除はいずれも一端で行われ、キューの挿入と削除は確かに両端で行われる.両端に挿入と削除が可能な両端キューもあります.配列で構成された両端キューについて、両端で挿入と削除操作を行う4つのプロセスを書き出し、実行時間が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は、2つのスタックを使用して1つのキューを実装し、キュー操作の実行時間を分析する方法を示す.
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は、2つのキューを使用して1つのスタックを実装し、スタック動作の実行時間を分析する方法を示す.
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)