【笔记】
栈:后进先出 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)