堆棧和隊列可能是使用頻率最高的數據結構,這裏主要記錄有關堆棧的一些用法和應用,由於堆棧是一種特殊的線性表,因此可以很自然地從相應的線性表類中派生出堆棧類。
可以派生出基於公式描述的堆棧類,也可以派生出基於鏈表結構的堆棧類。通過類的派生,可以大大簡化程序設計的任務,但同時代碼的執行效率有明顯損失。由於堆棧是一個很基本的數據結構,許多程序都要用到堆棧,爲了消除程序的額外開銷,可以把Stack定義成一個基類,而不是一個派生類。
自定義Stack如下:
template<class T>
class Stack {
// LIFO objects
public:
Stack(int MaxStackSize = 10);
~Stack() {delete [] stack;}
bool IsEmpty() const {return top == -1;}
bool IsFull() const {return top == MaxTop;}
T Top() const;
Stack<T>& Add(const T& x);
Stack<T>& Delete(T& x);
private:
int top; // current top of stack
int MaxTop; // max value for top
T *stack; // element array
};
template<class T>
Stack<T>::Stack(int MaxStackSize)
{// Stack constructor.
MaxTop = MaxStackSize - 1;
stack = new T[MaxStackSize];
top = -1;
}
template<class T>
T Stack<T>::Top() const
{// Return top element.
if (IsEmpty()) throw OutOfBounds(); // Top fails
return stack[top];
}
template<class T>
Stack<T>& Stack<T>::Add(const T& x)
{// Add x to stack.
if (IsFull()) throw NoMem(); // add fails
stack[++top] = x;
return *this;
}
template<class T>
Stack<T>& Stack<T>::Delete(T& x)
{// Delete top element and put in x.
if (IsEmpty()) throw OutOfBounds(); // delete fails
x = stack[top--];
return *this;
}
應用:括號匹配
在這個問題中將要匹配一個字符串中的左、右括號。例如,字符串 (a*
(b+c)+d)在位置1和4有左括號,在位置8和11有右括號。位置1的左括號匹配位置11
的右括號,位置4的左括號匹配位置8的右括號。對於字符串 (a+b))(,位置6的右括
號沒有可匹配的左括號,位置 7的左括號沒有可匹配的右括號。我們的目標是編寫
一個 C++程序,其輸入爲一個字符串,輸出爲相互匹配的括號以及未能匹配的括
號。注意,括號匹配問題可用來解決 C++程序中的{和}的匹配問題。
可以觀察到,如果從左至右掃描一個字符串,那麼每個右括號將與最近遇到的
那個未匹配的左括號相匹配。這種觀察結果使我們聯想到可以在從左至右的掃描過程
中把所遇到的左括號存放到堆棧內。每當遇到一個右括號時,就將它與棧頂的左括號
(如果存在)相匹配,同時從棧頂刪除該左括號。
產生匹配括號的程序:
#include <iostream.h>
#include <string.h>
#include <stdio.h>
#include "stack.h"
const int MaxLength = 100; // 最大的字符串長度
void PrintMatchedPairs(char *expr)
{// 括號匹配
Stack<int> s(MaxLength);
int j, length = strlen(expr);
// 從表達式 expr 中搜索 ( 和 )
for (int i = 1; I<=length; i++) {
if (expr[i - 1] ==' ( ' ) s.Add(I);
else if (expr[i - 1] ==' ) ' )
try{s.Delete(j);
cout << j <<' ' << i << endl;}
catch (OutOfBounds)
{ cout << "No match for right parenthesis" << " at " << i << endl;}
}
// 堆棧中所剩下的 (都是未匹配的
while(!s.IsEmpty()) {
s.Delete(j);
cout << "No match for left parenthesis at " <<j< endl;}
}
void main(void)
{
char expr[MaxLength];
cout << "Type an expression of length at most " << MaxLength << endl;
cin.getline(expr, MaxLength);
cout <<"The pairs of matching parentheses in" << endl;
puts (expr);
cout <<"are" << endl;
PrintMatcnedPairs(expr);
}
輸出結果: