數據結構複習篇:棧

二、棧

棧是一種“發育不良”的線性表,它具有與線性表相同的存儲結構(基於數組的或基於鏈於的),但棧的“缺陷”---不能像線性表那樣具有插入、刪除操作---反而給了它獨有的特色。在後面將會發現,遞歸,可以用棧來實現。 

在時間複雜度上,基於數組的棧AStack和鏈式棧LStack,在push()、pop()操作上,都是一個時間常數1。在我的測試中,10萬次push()和10萬次pop()後,基於數組的棧只比鏈式棧快一秒。但要注意AStack需要預先指定棧元素的最大個數,而LStack是動態分配的,元素個數在理論上不受限。

經常思考,我發現昨天在線性表那篇文章中,有一個設計錯誤,就是不應該把結點類Node與List類放在一個文件中,這是違反模塊化思想的。當我今天的棧中要用到結點時,應該可以很輕鬆的通過頭文件的方式把結點類引到我的代碼中。以下是一個最簡單的結點類界面(事實上可以採用可用空間表freelist的方式來定義結點類):

/*
定義常用於鏈表中的各種結點界面
文件名:NodeInterface.h
*/
#ifndef NODEINTERFACE_H
#define NODEINTERFACE_H

template
<class T> class Node    //單端結點,只含有一個指針
{
public:
    T element;
    Node 
* next;
public:
    Node(
const T &eVal, Node * nVal = NULL)
    {
        element 
= eVal;
        next 
= nVal;
    }
    Node(Node 
* nVal = NULL)
    {
        element 
= 0;
        next 
= nVal;
    }

};
#endif

以下是棧的界面及兩種實現的代碼:

 

 /*
 文件名:StackInterface.h
 
*/
#ifndef STACKINTERFACE_H
#define STACKINTERFACE_H

#include 
"NodeInterface.h"

 
//定義棧的界面
template<class T> class Stack
{
public:
    
virtual bool push(const T&= 0;    //入棧
    virtual bool pop(T&= 0;    //出棧
    virtual bool topValue(T&=0;    //棧頂元素值
};

/////////////////////////////////////
//基於數組的棧Array_based Satck
/////////////////////////////////////
template<class T> class AStack :public Stack<T>
{
private:
    
int maxSize;    //棧最多能容納的元素個數
    int top;    //指示棧中元素的實際個數,由於數組從0開始,(top-1)才指示了棧頂元素的下標
    T * listArray;    //array holding stack elements
public:
    AStack(
int size = 100)
    {
        maxSize 
= size;
        top 
= 0;
        listArray 
= new T[maxSize];
    }
    
~AStack()
    {
        delete [] listArray;
    }
    
bool push(const T &);
    
bool pop(T &);
    
bool topValue(T &);
    
int length() const
    {
        
return top;
    }

};

template
<class T> bool AStack<T>::push(const T & element)
{
    
if (top == maxSize)    //stack is full.
    {
        
return false;
    }
    listArray[top] 
= element;
    
++top;
    
return true;
}

template
<class T> bool AStack<T>::pop(T & ref_elem)
{
    
if (top == 0)    //no element in stack
    {
        
return false;
    }
    ref_elem 
= listArray[--top];
    
return true;
}

template
<class T> bool AStack<T>::topValue(T & ref_elem)
{
    
if (top == 0)    //no element in stack
    {
        
return false;
    }
    ref_elem 
= listArray[top-1];
    
return true;
}

///////////////////////////////////
//鏈式棧 Linked Stack
///////////////////////////////////
template<class T> class LStack :public Stack<T>
{
private:
    
int listSize;    //the number of elements,and that is the number of nodes
    Node<T> * top;    //與AStack棧不同,這裏,top指向棧頂元素
public:
    LStack()    
//不必限定元素的最大值
    {
        listSize 
= 0;
        top 
= NULL;
    }
    
~LStack()
    {

    }

    
bool push(const T &);
    
bool pop(T &);
    
bool topValue(T &);
    
void clear();
    
int length() const
    {
        
return listSize;
    }
};    

template
<class T> bool LStack<T>::push(const T &element)
{
    Node
<T> *tmp = new Node<T>(element,top);
    top 
= tmp;
    
++listSize;
    
return true;
}
template
<class T> bool LStack<T>::pop(T &ref_elem)
{
    
if (top == NULL)
    {
        
return false;    //棧中沒有元素
    }
    Node
<T> *tmp = top;
    top 
= top->next;
    ref_elem 
= tmp->element;
    delete tmp;
    
--listSize;
    
return true;

}
template
<class T> bool LStack<T>::topValue(T & ref_elem)
{
    
if (top == NULL)
    {
        
return false;    //none element in stack 
    }
    ref_elem 
= top->element;
    
return true;
}
template
<class T> void  LStack<T>::clear()
{
    Node
<T> * tmp;
    
while (top != NULL)
    {
        tmp 
= top;
        top 
= top->next;
        delete tmp;
    }
}
#endif

晚一些時候,我把用棧實現遞歸的方法,寫到這裏來。

 
發佈了3 篇原創文章 · 獲贊 4 · 訪問量 10萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章