棧的定義
- 棧是限定僅在表尾進行插入和刪除操作的線性表,允許操作的一端稱爲棧頂,不進行操作的一端稱爲棧底,不含任何數據元素的棧稱爲空棧。
- 棧具有“後進後出”的特性,就如同一疊盤子,要從這疊盤子中取出盤子或者放入一個盤子,只有在其頂部操作是最方便的。
1.棧的順序存儲結構——順序棧
//棧的順序存儲
template <class T>
class SeqStack
{
public:
SeqStack()
{
top = -1; //第一個元素入棧時,其下標爲0
}
~SeqStack() {}
void Push(T x) //入棧操作
{
if(top == StackSize - 1)
cout << "上溢";
else
{
//先使top指向下一個位置(top++),再將元素入棧
//通俗的來說,即先選好一個沙發,再請元素x入座。
data[++top] = x;
}
}
T Pop() //出棧操作
{
if(top == -1)
cout << "下溢";
else
{
//先將元素出棧,再使top指向上一個位置(top--)
//通俗的來說,即先請棧頂元素離開,再移走他的沙發。
return data[top--];
}
}
T GetTop()
{
if(top != -1)
return data[top];
}
int Empty()
{
top == -1 ? return 1 : return 0;
}
private:
T data[StackSize]; //存放棧元素的數組
int top; //指向棧頂元素的指針,特別注意的是棧爲空時top初始值爲-1
};
2.棧的鏈接存儲結構——鏈棧
//結點
template <class T>
struct Node
{
T data;
Node<T> * next;
};
//棧的鏈接存儲
template <class T>
class LinkStack
{
public:
LinkStack()
{
top = NULL;
}
~LinkStack();
void Push(T x)
{
Node<T> s = new Node<T>;
s->data = x;
s->next = top; //每個結點的next指針域都是指向上一個元素,而不是下一個元素。
top = s;
}
T Pop()
{
if(top == NULL)
cout << "下溢";
//暫存棧頂元素
T x = top->data;
Node<T> p = top;
top = top->next;
delete p;
return x;
}
T GetTop()
{
if(top != NULL)
return top->data;
}
int empty
{
top == NULL ? return 1 : return 0;
}
private:
Node<T> * top;
};
3.順序棧和鏈棧的比較
- 實現順序棧和鏈棧的基本操作算法所需的時間都是常數時間,所以唯一可以比較的就是空間性能。
- 順序表必須確定一個固定的長度,所以有存儲元素個數的限制和空間浪費的問題。
- 鏈棧沒有棧滿的問題,只有內存不夠的時纔會出現棧滿,但是每一個元素都需要一個指針域,從而產生了結構性開銷。
- 所以當棧的使用過程中元素個數變化較大時候,用鏈棧是適宜的;反之,應該採用順序棧。