數據結構圖文解析之:棧的簡介及C++模板實現

0. 數據結構圖文解析系列

數據結構系列文章
數據結構圖文解析之:數組、單鏈表、雙鏈表介紹及C++模板實現
數據結構圖文解析之:棧的簡介及C++模板實現
數據結構圖文解析之:隊列詳解與C++模板實現
數據結構圖文解析之:樹的簡介及二叉排序樹C++模板實現.
數據結構圖文解析之:AVL樹詳解及C++模板實現
數據結構圖文解析之:二叉堆詳解及C++模板實現
數據結構圖文解析之:哈夫曼樹與哈夫曼編碼詳解及C++模板實現

1. 棧的簡介

1.1棧的特色

棧(Stack)是一種線性存儲結構,它具備以下特色:html

  1. 棧中的數據元素遵照」先進後出"(First In Last Out)的原則,簡稱FILO結構。
  2. 限定只能在棧頂進行插入和刪除操做。

1.2棧的相關概念

棧的相關概念:node

  1. 棧頂與棧底:容許元素插入與刪除的一端稱爲棧頂,另外一端稱爲棧底。
  2. 壓棧:棧的插入操做,叫作進棧,也稱壓棧、入棧。
  3. 彈棧:棧的刪除操做,也叫作出棧。

例如咱們有一個存儲整型元素的棧,咱們依次壓棧:{1,2,3}
git

在壓棧的過程當中,棧頂的位置一直在」向上「移動,而棧底是固定不變的。
若是咱們要把棧中的元素彈出來:
github

出棧的順序爲三、二、1 ,順序與入棧時相反,這就是所謂的」先入後出「。
在彈棧的過程當中,棧頂位置一直在」向下「移動,而棧底一直保持不變。數組

若是你玩過一種稱爲漢諾塔的益智玩具,你就會知道遊戲中小圓盤的存取就是一種先進後出的順序,一個圓柱就是一個棧:
數據結構

1.3 棧的操做

棧的經常使用操做爲:測試

  1. 彈棧,一般命名爲pop
  2. 壓棧,一般命名爲push
  3. 求棧的大小
  4. 判斷棧是否爲空
  5. 獲取棧頂元素的值

1.4 棧的存儲結構

棧既然是一種線性結構,就可以以數組或鏈表(單向鏈表、雙向鏈表或循環鏈表)做爲底層數據結構。
本文咱們以數組、單向鏈表爲底層數據結構構建棧。編碼

2. 基於數組的棧實現

當以數組爲底層數據結構時,一般以數組頭爲棧底,數組頭到數組尾爲棧頂的生長方向:
3d

2.1 棧的抽象數據類型

棧提供瞭如上所述操做的相應接口。指針

template<typename T>
class ArrayStack
{
public:
    ArrayStack(int s = 10);    //默認的棧容量爲10
    ~ArrayStack();
 
public:
    T top();            //獲取棧頂元素
    void push(T t);        //壓棧操做
    T pop();            //彈棧操做
    bool isEmpty();        //判空操做
    int size();            //求棧的大小
 
private:
    int count;            //棧的元素數量
    int capacity;        //棧的容量
    T * array;            //底層爲數組
};
  1. count 爲棧的元素數量,capacity爲棧的容量,count<=capacity,當棧滿的時候,count = capacity。
  2. 本實現中不支持棧的動態擴容,棧滿的時候沒法再插入元素。棧的容量在定義棧的時候就須要指定,默認的棧容量爲10。

2.2 棧的具體實現

棧的實現仍是相對簡單的,很容易理解。這裏就再也不多此一舉了。

/*棧的判空操做*/
template <typename T>
bool ArrayStack<T>::isEmpty()
{
     return count == 0; //棧元素爲0時爲棧空
};
 
/*返回棧的大小*/
 template <typename  T>
int ArrayStack<T>::size()
{
     return count;
};
 
/*插入元素*/
template <typename T>
void ArrayStack<T>::push(T t)
{
     if (count != capacity)    //先判斷是否棧滿
     {
         array[count++] = t;   
     }
};
 
/*彈棧*/
template <typename T>
T ArrayStack<T>::pop()
{
     if (count != 0)    //先判斷是不是空棧
     {
         return array[--count];
     }
};
 
/*獲取棧頂元素*/
template <typename T>
T ArrayStack<T>::top()
{
     if (count != 0)
     {
         return array[count - 1];
     }
};

2.3 棧的代碼測試

int _tmain(int argc, _TCHAR* argv[])
{
    ArrayStack <int> p(5);
    for (int i = 0; i < 5; i++)
    {
        p.push(i);
    }
    cout << "棧的大小:"<<p.size() << endl;
    cout << "棧是否爲空:"<<p.isEmpty() << endl;
    cout << "棧頂元素:"<<p.top() << endl;
    cout << "依次出棧:" << endl;
    while (!p.isEmpty())
    {
        cout << p.pop() << endl;
    }
    getchar();
    return 0;
}

測試結果:

棧的大小:5
棧是否爲空:0
棧頂元素:4
依次出棧:
4
3
2
1
0

3. 基於單鏈表的棧

以鏈表爲底層的數據結構時,以鏈表頭爲做爲棧頂較爲合適,這樣方便節點的插入與刪除。壓棧產生的新節點將一直出如今鏈表的頭部;

3.1 鏈表節點

/*鏈表節點結構*/
template <typename T>
struct Node
{
    Node(T t) :value(t), next(nullptr){};
    Node() :next(nullptr){};
 
public:
    T value;
    Node<T>* next;
};
  1. value:棧中元素的值
  2. next:鏈表節點指針,指向直接後繼

3.2 棧的抽象數據類型

基於鏈表的棧提供的接口與基於數組的棧一致。

/*棧的抽象數據結構*/
template <typename T>
class LinkStack
{
public:
     LinkStack();
     ~LinkStack();
public:
 
     bool isEmpty();
     int size();
     void push(T t);
     T pop();
     T top();
 
private:
 
     Node<T>* phead;
     int count;
};

3.3 棧的具體實現

/*返回棧的大小*/
template <typename T>
int LinkStack<T>::size()
{
     return count;
};
/*棧的判空操做*/
template <typename T>
bool LinkStack<T>::isEmpty()
{
     return count == 0;
};
/*插入元素*/
template<typename T>
void LinkStack<T>::push(T t)
{
     Node <T> *pnode = new  Node<T>(t);
     pnode->next = phead->next;
     phead->next = pnode;
     count++;
};
/*彈棧*/
template <typename T>
T LinkStack<T>::pop()
{
     if (phead->next != nullptr) //棧空判斷
     {
         Node<T>* pdel = phead->next;
         phead->next = phead->next->next;
         T value = pdel->value;
         delete pdel;
         count--;
         return value;
     }
};
/*獲取棧頂元素*/
template <typename T>
T LinkStack<T>::top()
{
    if (phead->next!=nullptr)
        return phead->next->value;
};

3.4 棧的代碼測試

int _tmain(int argc, _TCHAR* argv[])
{
    LinkStack <string> lstack;
    lstack.push("hello");
    lstack.push("to");
    lstack.push("you!");
 
    cout << "棧的大小:" << lstack.size() << endl;
    cout <<"棧頂元素:"<< lstack.top() << endl;
 
    while (!lstack.isEmpty())
    {
        lstack.pop();
    }
 
    cout << "棧的大小:" << lstack.size() << endl;
 
    getchar();
    return 0;
}

測試結果:

棧的大小:3
棧頂元素:you!
棧的大小:0

4. 棧的完整代碼

基於數組的棧: https://github.com/huanzheWu/Data-Structure/blob/master/Stack/Main/Main/ArrayStack.h
基於單鏈表的棧:https://github.com/huanzheWu/Data-Structure/blob/master/singleList/singleList/singleList.h

原創文章,轉載請註明出處:http://www.cnblogs.com/QG-whz/p/5170418.html

相關文章
相關標籤/搜索