1. 程式人生 > >資料結構筆記之用C++實現順序棧和鏈式棧

資料結構筆記之用C++實現順序棧和鏈式棧

這裡介紹兩種實現棧的方式:“順序棧”和“鏈式棧”,各有各的優缺點。

不管是“順序棧”還是“鏈式棧”,我們可以先定義一個棧的ADT(抽象資料型別),如下面的“stack.h”

#ifndef STACK_H
#define STACK_H
const int maxSize=50;

template <class T>
class Stack{
public:
    Stack(){};
    virtual void Push(const T& x)=0;
    virtual bool Pop(T& x)=0;
    virtual bool getTop(T& x)const
=0; virtual bool isEmpty()const=0; virtual bool isFull()const=0; virtual int getSize() const=0; }; #endif
關於模版類“template”的使用可以參考網上的教程,這裡定義了棧的幾個基本操作:構造棧,進棧,退棧,獲取棧頂元素,判斷棧空,判斷棧滿,獲取棧的元素個數 

1、“順序棧”的實現

建立“seqstack.h”,並在裡面實現順序棧

/*
** 順序棧的模板類及其成員函式的實現,建立“seqstack.h”
*/
#ifndef SEQSTACK_H
#define SEQSTACK_H
#include <assert.h> #include <iostream> #include "stack.h" using namespace std; const int stackIncreament=20; template <class T> class SeqStack :public Stack<T>{ public: /* ** 建立一個空棧 */ SeqStack(int sz=50); /* ** 解構函式 */ ~SeqStack(){delete[]elements;} /* ** 進棧 */
void Push(const T& x); /* ** 退棧 */ bool Pop(T& x); /* ** 獲取棧頂元素 */ bool getTop(T& x)const; /* ** 判斷棧是否為空 */ bool isEmpty()const {return(top == -1)?true:false;} /* ** 判斷棧是否為滿 */ bool isFull()const {return(top == maxSize-1)?true:false;} /* ** 獲取棧的元素個數 */ int getSize()const {return top+1;} /* ** 清空棧 */ void MakeEmpty(){top=-1;} /* ** 輸出棧中元素的過載操作<< */ friend ostream& operator << (ostream& os,SeqStack<T>& s); private: /* ** 存放棧中元素的棧陣列 */ T* elements; /* ** 棧頂元素 */ int top; /* ** 棧最大可容納的元素個數 */ int maxSize; /* ** 棧溢位的處理 */ void overflowProcess(); }; //由於編譯器的關係,模板類成員函式必須和申明在一個同一個“.h”檔案裡 template<class T> SeqStack<T>::SeqStack(int sz/* =50 */):top(-1),maxSize(sz){ elements=new T[maxSize]; assert(elements!=NULL); }; template<class T> void SeqStack<T>::overflowProcess(){ T * newArray = new T[maxSize+stackIncreament]; if (newArray==NULL){cerr<<"add stack area failed!"<<endl;exit(1);} for (int i=0;i<=top;i++) { newArray[i]=elements[i]; } maxSize=maxSize+stackIncreament; delete[]elements; elements=newArray; }; template<class T> void SeqStack<T>::Push(const T& x){ if (isFull()==true) { overflowProcess(); } elements[++top]=x; }; template<class T> bool SeqStack<T>::Pop(T& x) { if (isEmpty()==true) { return false; } x=elements[top--]; return true; }; template<class T> bool SeqStack<T>::getTop(T& x)const { if (isEmpty()==true) { return false; } x=elements[top]; return true; }; template<class T> ostream& operator<<(ostream& os,SeqStack<T>& s){ os<<"top=="<<s.top<<endl; for (int i=0;i<=s.top;i++) { os<<i<<":"<<s.elements[i]<<endl; } return os; }; #endif

2、“鏈式棧”的實現

首先先定義一個結點結構體“LinkedList.h”

/*
** 單鏈表結點的結構體定義
*/
#ifndef LINKEDLIST_H
#define LINKEDLIST_H

template <class T>
struct LinkNode{
    /*
    ** 資料域
    */
    T data;

    /*
    ** 鏈指標域
    */
    LinkNode<T> *link;

    /*
    ** 僅初始化指標成員的建構函式
    */
    LinkNode(LinkNode<T> *ptr = NULL){link=ptr;}

    /*
    ** 初始化資料和指標成員的建構函式
    */
    LinkNode(const T& item,LinkNode<T> *ptr=NULL)
    {
        data=item;
        link=ptr;
    }
};
#endif

接著實現“鏈式棧”“LinkedStack.h”

/*
** 鏈式棧的模板類及其成員函式的實現
*/
#ifndef LINKEDSTACK_H
#define LINKEDSTACK_H

#include "LinkedList.h"
#include "stack.h"
#include "stdafx.h"
#include "seqstack.h"
#include <iostream>

template<class T>
class LinkedStack:public Stack<T>{
public:
    /*
    ** 建構函式,置空棧
    */
    LinkedStack():top(NULL){};

    /*
    ** 解構函式
    */
    ~LinkedStack(){makeEmpty();};

    /*
    ** 進棧
    */
    void Push(const T& x);

    /*
    ** 退棧
    */
    bool Pop(T& x);

    /*
    ** 讀取棧頂元素
    */
    bool getTop(T& x)const;

    /*
    ** 判斷是否棧為空
    */
    bool isEmpty()const{return(top==NULL)?true:false;}

    /*
    ** 鏈式表不需要判斷是否棧滿,但必須將虛擬函式例項化,這裡預設返回為true
    */
    bool isFull()const{return true;}

    /*
    ** 求棧的元素個數
    */
    int getSize()const;

    /*
    ** 清空棧
    */
    void makeEmpty();

    /*
    ** 輸出棧中元素的過載操作<<
    */
    friend ostream& operator<<(ostream& os,SeqStack<T>& s);

private:

    /*
    ** 棧頂指標,即鏈頭指標
    */
    LinkNode<T> *top;
};

template<class T>
void LinkedStack<T>::makeEmpty(){
    LinkNode<T> *p;
    while(top !=NULL)
    {
        p=top;
        top=top->link;
        delete p;
    }
};

template<class T>
bool LinkedStack<T>::Pop(T& x)
{
    if (isEmpty()==true)
    {
        return false;
    }
    LinkNode<T> *p=top;
    top=top->link;
    x=p->data;
    delete p;
    return true;
};

template<class T>
void LinkedStack<T>::Push(const T& x){
    top=new LinkNode<T>(x,top);
    assert(top !=NULL);
};

template<class T>
bool LinkedStack<T>::getTop(T& x)const{
    if (isEmpty()==true)
    {
        return false;
    }
    x=top->data;
    return true;
};
template<class T>
int LinkedStack<T>::getSize()const{
    int k=0;
    LinkNode<T> *p=top;
    while (p !=NULL)
    {
        p=p->link;
        k++;
    }
    /*
    **一個成員函式宣告為const,則這個成員函式不修改資料成員,這個書裡面寫錯了
    */
    /*while (top !=NULL)
    {
        top=top->link;
        k++;
    }*/
    return k;
};
template<class T>
ostream& operator<<(ostream& os,LinkedStack<T>& s){
    os<<"get stack size is"<<s.getSize()<<endl;
    LinkNode<T> *p=s.top;
    int i=0;
    while(p!=NULL)
    {
        os<<++i<<":"<<p->data<<endl;
        p=p->link;
    }
    return os;
};
#endif

3、Main函式呼叫


#include "stdafx.h"
#include "seqstack.h"
#include "stack.h"
#include "LinkedStack.h"
#include "LinkedList.h"


void _tmain(int argc, _TCHAR* argv[])
{
    //申明一個int型的順序棧
    SeqStack<int>inArray(maxSize);
    //申明一個int型的鏈式棧
    LinkedStack<int>linkArray;
    int seqtop,linktop;
    for (int i=0;i<50;i++)
    {
        //進棧
        inArray.Push(i);
        linkArray.Push(i);
        //獲取棧頂元素,獲取不會進行出棧操作,可以對比下面的Pop操作對比
        inArray.getTop(seqtop);
        linkArray.getTop(linktop);
        //輸出棧頂元素
        cout<<seqtop<<"  "<<linktop<<endl;
    }
    int size=inArray.getSize();
    cout<<"the seqstack current size is "<<size<<endl;
    size=linkArray.getSize();
    cout<<"the linkstack current size is "<<size<<endl;
    //清空棧
    linkArray.makeEmpty();
    size=linkArray.getSize();
    cout<<"the linkstack current size is "<<size<<endl;
    while(!inArray.isEmpty())
    {
        inArray.Pop(seqtop);
        //輸出出棧元素,驗證棧是“LIFO(後進先出)”
        cout<<seqtop<<endl;
        cout<<"the stack current size is "<<inArray.getSize()<<endl;
    }
    //房子視窗退出
    cin>>size;
}