数据结构复习篇:栈

来源:互联网 发布:下载magnet的软件 编辑:程序博客网 时间:2024/05/01 01:00

二、栈

栈是一种“发育不良”的线性表,它具有与线性表相同的存储结构(基于数组的或基于链于的),但栈的“缺陷”---不能像线性表那样具有插入、删除操作---反而给了它独有的特色。在后面将会发现,递归,可以用栈来实现。 

在时间复杂度上,基于数组的栈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

晚一些时候,我把用栈实现递归的方法,写到这里来。

原创粉丝点击