数据结构与算法——栈

1 概述

1.1 定义

栈是一种特殊的线性表,插入(入栈或压栈)和删除(出栈或弹栈)都在同一端进行。这一端成为栈顶,另一端为栈底。下图为栈的示意图。
在这里插入图片描述
1.2 抽象数据类型
在这里插入图片描述
用c++语言实现上图stack抽象类,代码如下:

template<class T>
class stack 
{
   public:
      virtual ~stack() {}
      virtual bool empty() const = 0;
                  // return true iff 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
};

2 数组描述

2.1 由数组派生类实现

由于栈是特殊的线性表,所以由arrayList和stack派生得到。

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);
	}
};

注:基类方法get和erase遇到空栈抛出illegalIndex形式,在栈中没有实际意义,可以通过try-catch代替对空栈的检查;LIFO原则可以在类derivedArrayStack的实例上贯彻执行

2.2 类arrayStack

利用上述派生方法得到一个栈类的时候,性能会有损失,例如插入一个元素时,push实际上调用的是arrayList的insert方法,会对下标进行检查,还要进行往回复制,这两个操作在栈中是不必要的。

所以直接从stack抽象类继承得到arrayStack类。

类声明:

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;
}

3 链表描述

3.1 类derivedLinkedStack

此类从chain类派生,实现了stack抽象类。方法实现和derivedArrayStack基本相同,需要注意的是:方法get、insert、和erase的调用中作为索引的实参应改为0,使这些操作发生在链表的左端。声明如下:

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

3.1 类linkedStack

定制地开发链式描述的栈: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
};

4 应用

  • 括号匹配
  • 汉诺塔
  • 列车车厢重拍
  • 开关盒布线
  • 离线等价类问题
  • 迷宫老鼠
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值