歡迎光臨
每天分享高質量文章

詳解棧及其實現

(點選上方公眾號,可快速關註)

轉自:melonstreet

http://www.cnblogs.com/QG-whz/p/5170418.html

好文投稿, 請點選 → 這裡瞭解詳情


棧的特點


棧(Stack)是一種線性儲存結構,它具有如下特點:


1、棧中的資料元素遵守”先進後出”(First In Last Out)的原則,簡稱FILO結構。

2、限定只能在棧頂進行插入和刪除操作。

棧的相關概念


1、棧頂與棧底:允許元素插入與刪除的一端稱為棧頂,另一端稱為棧底。

2、壓棧:棧的插入操作,叫做進棧,也稱壓棧、入棧。

3、彈棧:棧的刪除操作,也叫做出棧。


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



在壓棧的過程中,棧頂的位置一直在”向上“移動,而棧底是固定不變的。


如果我們要把棧中的元素彈出來:



出棧的順序為3、2、1 ,順序與入棧時相反,這就是所謂的”先入後出“。


在彈棧的過程中,棧頂位置一直在”向下“移動,而棧底一直保持不變。


如果你玩過一種稱為漢諾塔的益智玩具,你就會知道遊戲中小圓盤的存取就是一種先

進後出的順序,一個圓柱就是一個棧:


棧的操作


棧的常用操作為:


1、彈棧,通常命名為pop

2、壓棧,通常命名為push

3、求棧的大小

4、判斷棧是否為空

5、獲取棧頂元素的值

棧的儲存結構


棧既然是一種線性結構,就能夠以陣列或連結串列(單向連結串列、雙向連結串列或迴圈連結串列)作為底層資料結構。


本文我們以陣列、單向連結串列為底層資料結構構建棧。

基於陣列的棧實現


當以陣列為底層資料結構時,通常以陣列頭為棧底,陣列頭到陣列尾為棧頂的生長方向:


棧的抽象資料型別


棧提供瞭如上所述操作的相應介面。


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。


棧的具體實現


棧的實現還是相對簡單的,很容易理解。


/*棧的判空操作*/

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[count1];

     }

};

棧的程式碼測試


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

基於單連結串列的棧


以連結串列為底層的資料結構時,以連結串列頭為作為棧頂較為合適,這樣方便節點的插入與刪除。壓棧產生的新節點將一直出現在連結串列的頭部;


連結串列節點


/*連結串列節點結構*/

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:連結串列節點指標,指向直接後繼

棧的抽象資料型別


基於連結串列的棧提供的介面與基於陣列的棧一致。


/*棧的抽象資料結構*/

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;

};

棧的具體實現

/*傳回棧的大小*/

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;

};

棧的程式碼測試

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

覺得本文有幫助?請分享給更多人

關註「演演算法愛好者」,修煉程式設計內功

贊(0)

分享創造快樂