《数据结构、算法与应用》 C++描述 -- 第8章 栈 学习笔记

一、定义

定义:

栈(stack)是一种特殊的线性表,其插入(也称为入栈或压栈)和删除(也成为出栈或弹栈)操作都在表的同一端进行。这一端称为栈顶(top),另一端成为栈底(bottom)。可以使用前面实现过的基于数组和链表的线性表实现栈结构。在计算过程中经常使用。

现实中的应用:

  • 打印机纸盘
  • 自助餐厅的盘子等

抽象数据类型:

template<class T>
class stack 
{
   public:
      virtual ~stack() {}
      virtual bool empty() const = 0;
                  // return true if stack is empty
      virtual int size() const = 0;
                  // return number of elements in stack
      virtual T& top() = 0;
                  // return reference to the top element
      virtual void pop() = 0;
                  // remove the top element
      virtual void push(const T& theElement) = 0;
                  // insert theElement at the top of the stack
};

二、数组描述

栈的插入和删除都被限制在一端进行,因此可以选择数组的左端或右端定义为栈顶。而数组尾端操作效率较高(从右端插入和删除不需要移动其他元素),可将右端定义为栈顶。

1. 使用arrayList派生类实现

template<class T>
class derivedArrayStack : private arrayList<T>, public stack<T>
{
   public:
      derivedArrayStack(int initialCapacity = 10): arrayList<T> (initialCapacity) {}
      bool empty() const{
					return arrayList<T>::empty();
			}
      int size() const{
					return arrayList<T>::size();
			}
      T& top(){
          if (arrayList<T>::empty())
             throw stackEmpty();
          return get(arrayList<T>::size() - 1);
      }
      void pop()
      {
         if (arrayList<T>::empty())
            throw stackEmpty();
         erase(arrayList<T>::size() - 1);
      }
      void push(const T& theElement)
      {insert(arrayList<T>::size(), theElement);}
};

评论

 虽然上述方法能很简单的实现栈,但会带来性能上的损失。例如当往栈中插入一个元素是,push方法会调用arrayList 的insert方法,插入元素前要对下标进行检查,可能要将数组加长,而且还要往回复制。但下标检查和往回复制都是不必要的,因为我们总是将新元素插到最右端。

因此,可用数组实现性能更好的栈。

三、srrayStack类

template<class T>
class arrayStack : public stack<T>
{
   public:
      arrayStack(int initialCapacity = 10);
      ~arrayStack() {delete [] stack;}
      bool empty() const {return stackTop == -1;}
      int size() const
          {return stackTop + 1;}
      T& top()
         {
            if (stackTop == -1)
               throw stackEmpty();
            return stack[stackTop];
         }
      void pop()
           {
              if (stackTop == -1)
                 throw stackEmpty();
              stack[stackTop--].~T();  // destructor for T
           }
      void push(const T& theElement);
   private:
      int stackTop;         // current top of stack
      int arrayLength;      // stack capacity
      T *stack;           // element array
};

template<class T>
arrayStack<T>::arrayStack(int initialCapacity)
{// Constructor.
   if (initialCapacity < 1)
   {ostringstream s;
    s << "Initial capacity = " << initialCapacity << " Must be > 0";
    throw illegalParameterValue(s.str());
   }
   arrayLength = initialCapacity;
   stack = new T[arrayLength];
   stackTop = -1;
}

template<class T>
void arrayStack<T>::push(const T& theElement)
{// Add theElement to stack.
   if (stackTop == arrayLength - 1)
      {// no space, double capacity
         changeLength1D(stack, arrayLength, 2 * arrayLength);
         arrayLength *= 2;
      }

   // add at stack top
   stack[++stackTop] = theElement;
}

四、链表描述

同样的可以使用链表描述栈。使用左端作为栈顶的性能要优于使用右端作为栈顶。因此,将链表的左端作为栈顶。

linkedStack类实现

template<class T>
class linkedStack : public stack<T>
{
   public:
      linkedStack(int initialCapacity = 10)
            {stackTop = NULL; stackSize = 0;}
      ~linkedStack();
      bool empty() const
           {return stackSize == 0;}
      int size() const
          {return stackSize;}
      T& top()
         {
            if (stackSize == 0)
               throw stackEmpty();
            return stackTop->element;
         }
      void pop();
      void push(const T& theElement)
           {
              stackTop = new chainNode<T>(theElement, stackTop);
              stackSize++;
           }
   private:
      chainNode<T>* stackTop;  // pointer to stack top
      int stackSize;           // number of elements in stack
};

template<class T>
linkedStack<T>::~linkedStack()
{// Destructor.
   while (stackTop != NULL)
   {// delete top node
      chainNode<T>* nextNode = stackTop->next;
      delete stackTop;
      stackTop = nextNode;
   }
}

template<class T>
void linkedStack<T>::pop()
{// Delete top element.
   if (stackSize == 0)
      throw stackEmpty();

   chainNode<T>* nextNode = stackTop->next;
   delete stackTop;
   stackTop = nextNode;
   stackSize--;
}

五、性能对比

数组描述的性能要好于链表描述的栈。

原因

  • 数组的空间分配是一组一组进行的;而链表的空间分配是一个节点一个节点进行的。
  • 从占用内存空间上看:链表中每个节点还要保存指向下一个元素的指针,所需要分配的空间也相对更大。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值