1. 程式人生 > >資料結構筆記三: 棧

資料結構筆記三: 棧

1. 棧的基本概念

棧是限定只在表頭進行插入(入棧)和刪除(出棧)操作的線性表,表頭端稱為棧頂,表尾端稱為棧底。
設有棧

S = ( a 1 , a 2 , , a n
) 則一般稱 a 1 為棧底元素, a
n
為棧頂元素,按 a 1 , a 2 , , a n 的順序依次進棧,出棧的第一個元素為棧頂元素,也就是說棧是按照後進先出的原則進行。
棧的實現和線性表類似,有兩種方法——順序棧和鏈棧

2. 順序棧

//.hpp檔案
#pragma once

#define DEFAULT_SIZE 10


//順序棧類
template<typename elemType>
class SqStack
{
private:
//順序棧的資料成員
    int count;
    int maxSize;
    elemType* elems;

    //輔助函式
    bool Full() const; //判斷棧是否已滿
    void Init(int size);//對棧進行初始化

public:
//抽象資料型別方法宣告及過載編譯系統預設方法宣告
    SqStack(int size = DEFAULT_SIZE);//建構函式
    virtual ~SqStack();//解構函式
    int getLength() const;//求棧的長度
    bool isEmpty() const;//判斷棧是否為空
    void Clear();//清空棧
    void Traverse(void(*Visit)(elemType &));//遍歷棧
    bool Push(const elemType &e);//入棧
    bool Top(elemType &e) const;//返回棧頂元素
    bool Pop(elemType &e);//出棧

    SqStack(SqStack<elemType> &copy);//複製建構函式
    SqStack<elemType>& operator=(SqStack<elemType> &copy);//賦值運算子過載

};

//順序棧的實現
template<typename elemType>
bool SqStack<elemType>::Full() const
{
    return count == maxSize;
}

template<typename elemType>
void SqStack<elemType>::Init(int size)
{
    maxSize = size;
    if (elems != NULL) delete[] elems;
    elems = new elemType[maxSize];
    count = 0;
}

template<typename elemType>
SqStack<elemType>::SqStack(int size = DEFAULT_SIZE)
{
    elems = NULL;
    Init(size);
}

template<typename elemType>
SqStack<elemType>::~SqStack()
{
    if (elems != NULL) delete[] elems;
}

template<typename elemType>
int SqStack<elemType>::getLength() const
{
    return count;
}

template<typename elemType>
bool SqStack<elemType>::isEmpty() const
{
    return count == 0;
}

template<typename elemType>
void SqStack<elemType>::Clear()
{
    count = 0;
}

template<typename elemType>
void SqStack<elemType>::Traverse(void(*Visit)(elemType &))
{
    for (int curPosition = 1; curPosition <= this->getLength(); curPosition++)
    {
        (*Visit)(elems[curPosition - 1]);
    }
}

template<typename elemType>
bool SqStack<elemType>::Push(const elemType &e)
{
    if (Full())
    {
        return false;
    } 
    else
    {
        elems[count++] = e;
        return true;
    }
}

template<typename elemType>
bool SqStack<elemType>::Top(elemType &e) const
{
    if (isEmpty())
    {
        return false;
    } 
    else
    {
        e = elems[count - 1];
        return true;
    }
}

template<typename elemType>
bool SqStack<elemType>::Pop(elemType &e)
{
    if (isEmpty())
    {
        return false;
    } 
    else
    {
        e = elems[--count];
        return true;
    }
}

template<typename elemType>
SqStack<elemType>::SqStack(SqStack<elemType> &copy)
{
    elems = NULL;
    Init(copy.maxSize);//這裡為什麼可以直接訪問私有成員maxSize
    count = copy.getLength();
    for (int curPosition = 1; curPosition <= count; curPosition++)
    {
        elems[curPosition - 1] = copy.elems[curPosition - 1];
    }
}

template<typename elemType>
SqStack<elemType>& SqStack<elemType>::operator =(SqStack<elemType> &copy)
{
    if (&copy != this)
    {
        Init(copy.maxSize);
        count = copy.getLength();
        for (int curPosition = 1; curPosition <= count; curPosition++)
        {
            elems[curPosition - 1] = copy.elems[curPosition - 1];
        }
    }
    return *this;
}
//測試檔案
#include <iostream>
#include "SqStack.hpp"

using namespace std;

template<typename elemType>
void Visit2(elemType &e)
{
    cout << e << endl;
}

int main(int argc, char* argv[])
{
    SqStack<int> mySqStack;
    mySqStack.Push(1);
    mySqStack.Push(2);
    mySqStack.Traverse(Visit2);//使用函式指標!!!

    SqStack<int> mySqStack1(mySqStack);
    mySqStack1.Traverse(Visit2);
    getchar();
    return 0;
}

3. 連結串列棧

在程式中同時使用多個棧的情形下,使用鏈式棧不但可以提高儲存效率,同時還可以達到共享儲存空間的目的。(如何達到共享儲存空間的目的?)

//.hpp檔案
#pragma once

//節點類
template<typename elemType>
struct Node
{
    //資料成員
    elemType data;//資料域
    Node<elemType>* next;//指標域

    //建構函式
    Node();//無參建構函式
    Node(elemType item, Node<elemType>* Link = NULL);//已知資料域和指標域建立結構
};

//節點類的實現部分
template<typename elemType>
Node<elemType>::Node()
//操作結果:構造指標域為空的節點
{
    this->next = NULL;
}

template<typename elemType>
Node<elemType>::Node(elemType item, Node<elemType>* Link)
//操作結果:構造資料域為item指標域為Link的節點
{
    this->data = item;
    this->next = Link;
}


//鏈棧類
template<typename elemType>
class LinkStack
{
private:
    //鏈棧實現的資料成員
    Node<elemType>* top;//棧頂指標

    //輔助函式
    void Init();//初始化棧

public:
    //抽象資料型別方法宣告及過載編譯系統預設方法宣告
    LinkStack();//無參建構函式
    virtual ~LinkStack();//解構函式
    int getLength() const;//獲取棧的長度
    bool isEmpty() const;//判斷棧是否為空
    void Clear();//將棧清空
    void Traverse(void(*Visit)(elemType &e));//遍歷棧
    bool Push(const elemType & e);//入棧
    bool Top(elemType& e) const;//返回棧頂的元素
    bool Pop(elemType& e);//出棧

    LinkStack(LinkStack<elemType> & copy);//複製建構函式
    LinkStack<elemType>& operator=(LinkStack<elemType> & copy);//過載賦值運算子
};


//鏈棧類的實現
template<typename elemType>
void LinkStack<elemType>::Init()
//對鏈棧進行初始化,外部不可呼叫
{
    top = NULL;
}

template<typename elemType>
LinkStack<elemType>::LinkStack()
{
    Init();
}

template<typename elemType>
LinkStack<elemType>::~LinkStack()
{
    Clear();
}

template<typename elemType>
int LinkStack<elemType>::getLength() const
{
    int count = 0;
    for (Node<elemType>* curPosition = top; curPosition != NULL; curPosition = curPosition->next)
    {
        count++;
    }
    return count;
}

template<typename elemType>
bool LinkStack<elemType>::isEmpty() const
{
    return top == NULL;
}

template<typename elemType>
void LinkStack<elemType>::Clear()
{
    elemType e;
    while (top != NULL)
    {
        Pop(e);//刪除連結串列元素的技巧
    }
}

template<typename elemType>
void LinkStack<elemType>::Traverse(void(*Visit)(elemType &e))
{
    for (Node<elemType>* curPosition = top; curPosition != NULL; curPosition = curPosition->next)
    {
        (*Visit)(curPosition->data);
    }
}

template<typename elemType>
bool LinkStack<elemType>::Push(const elemType & e)
{

    Node<elemType>* tempNode = top;
    top = new Node < elemType > ;
    if (top == NULL)//如果動態記憶體耗盡
    {
        return false;
    }
    top->data = e;
    top->next = tempNode;
    return true;
}

template<typename elemType>
bool LinkStack<elemType>::Top(elemType& e) const
{
    if (isEmpty())
    {
        return false;
    }
    else
    {
        e = top->data;
        return true;
    }
}

template<typename elemType>
bool LinkStack<elemType>::Pop(elemType& e)
{
    if (isEmpty())
    {
        return false;
    } 
    else
    {
        e = top->data;
        Node<elemType>* tempPtr = top;
        top = top->next;
        delete tempPtr;
        return true;
    }
}

template<typename elemType>
LinkStack<elemType>::LinkStack(LinkStack<elemType> & copy)
{
    if (copy.isEmpty())
    {
        Init();
    }
    else
    {
        top = new Node<elemType>(copy.top->data);
        Node<elemType>* tempPtr = top;
        for (Node<elemType>* curPosition = copy.top->next; curPosition != NULL; curPosition = curPosition->next)
        {
            tempPtr->next = new Node<elemType>(curPosition->data);
            tempPtr = tempPtr->next;
        }

    }
}

template<typename elemType>
LinkStack<elemType>& LinkStack<elemType>::operator=(LinkStack<elemType> & copy)
{
    if (&copy != this)
    {
        if (copy.isEmpty())
        {
            Init();
        }
        else
        {
            Clear();
            top = new Node<elemType>(copy.top->data);
            Node<elemType>* tempPtr = top;
            for (Node<elemType>* curPosition = copy.top->next; curPosition != NULL; curPosition = curPosition->data)
            {
                tempPtr->next = new Node<elemType>(copy.top->data);
                tempPtr = tempPtr->next;
            }
        }
    }
    return *this;
}
//測試檔案
#include "LinkStack.hpp"
#include <iostream>

using namespace std;
template<typename elemType>
void Visit2(elemType &e)
{
    cout << e << endl;
}

int main(int argc, char* argv[])
{
    LinkStack<int> myLinkStack;
    using namespace std;

    myLinkStack.Push(1);
    myLinkStack.Push(2);
    myLinkStack.Push(3);
    myLinkStack.Traverse(Visit2);//使用函式指標!!!

    LinkStack<int> mySqStack1(myLinkStack);
    mySqStack1.Traverse(Visit2);

    getchar();
    return 0;
}