栈的三种实现(静态数组、动态数组及指针)

来源:互联网 发布:成都好吃网络的蛋糕店 编辑:程序博客网 时间:2024/06/06 04:47

 本文有关栈的介绍部分参考自网站数据结构。

  1. 栈

   1.1 栈的定义

  栈(Stack)是限制仅在表的一端进行插入和删除运算的线性表。
  (1)通常称插入、删除的这一端为栈顶(Top),另一端称为栈底(Bottom)。
  (2)当表中没有元素时称为空栈
  (3)栈为后进先出(Last In First Out)的线性表,简称为LIFO表
     栈的修改是按后进先出的原则进行。每次删除(退栈)的总是当前栈中"最新"的元素,即最后插入(进栈)的元素,而最先插入的是被放在栈的底部,要到最后才能删除。
      

  【示例】元素是以a1,a2,…,an的顺序进栈,退栈的次序却是an,an-1,…,a1

   1.2 栈的运算

  (1)initStack(S)
     构造一个空栈S。
  (2)isEmpty(S)
     判栈空。若S为空栈,则返回TRUE,否则返回FALSE。
  (3)isFull(S)
     判栈满。若S为满栈,则返回TRUE,否则返回FALSE。
   注意:
     
该运算只适用于栈的顺序存储结构。
  (4)push(S,x)
     进栈。若栈S不满,则将元素x插入S的栈顶。
  (5)pop(S)
     退栈。若栈S非空,则将S的栈顶元素删去,并返回该元素。
  (6)top(S)
     取栈顶元素。若栈S非空,则返回栈顶元素,但不改变栈的状态。

  2. 栈的三种实现

  我在实现的时候,栈的基本函数都有(isEmpty、push、pop、top)。因为我是用面向对象的方法来设计栈,所以栈的初始化、拷贝构造、赋值运算符重载等也都具备。另外,我采取了C++中的模板类来设计栈,使得该栈设计能适应更多的场合。

   2.1 基于静态数组

  基于静态数组的栈的最大特点就是栈的大小是固定的,用户在初始化之后就无法改变。在编译期,编译器就已经给这个栈分配好内存,在“内存的栈”上分配。

  这是我所设计的栈模板类:

复制代码
 1 template<class T, int defCapacity = 1024> 2 class Stack 3 { 4 public: 5     Stack(); 6     virtual ~Stack(); 7     bool isEmpty(); 8     bool push(T val);   // 进栈。若栈不满,则将元素插入栈顶。 9     T top();            // 取栈顶元素。若栈S非空,则返回栈顶元素,但不改变栈的状态。10     bool pop();         // 退栈。若栈非空,则将栈顶元素删去,并返回是否退栈成功的标志。11                         // 这里没有采用返回被删栈顶元素的原因在于这里写的是一个模板,12                         // 当栈为空的时候不方便返回。当然,这个问题是可以通过断言或13                         // 抛异常来解决的。具体做法可根据具体情况来定。14     int getSizeOfStack();15 16 private:17     T stack[defCapacity];18     int sizeOfStack;19 20 };
复制代码

  具体实现代码为:

 stack.hpp

  Boost单元测试代码为:

 BoostUnitTest.cpp

   2.2 基于动态数组

  基于动态数组的栈的特点是栈的大小是可以运行时改变的,即可以通过重新分配栈来实现栈的扩容与压缩。还有,跟基于静态数组的栈不一样的是,基于动态数组的栈是在程序运行时才分配(堆上分配)。

  栈模板类:

复制代码
 1 template<class T, int defCapacity> 2 class Stack 3 { 4 public: 5     Stack(); 6     virtual ~Stack(); 7     Stack(const Stack& orig);    // 拷贝构造函数 8     Stack& operator=(const Stack& orig);    // 赋值运算符重载 9     bool isEmpty();10     bool push(T val);       // 进栈。若栈不满,则将元素插入栈顶。11     T top();                // 取栈顶元素。若栈S非空,则返回栈顶元素,但不改变栈的状态。12     bool pop();             // 退栈。若栈非空,则将栈顶元素删去,并返回是否退栈成功的标志。13                             // 这里没有采用返回被删栈顶元素的原因在于这里写的是一个模板,14                             // 当栈为空的时候不方便返回。当然,这个问题是可以通过断言或15                             // 抛异常来解决的。具体做法可根据具体情况来定。16     int getSizeOfStack();17 18 private:19     T * stack;20     int capacity;21     int sizeOfStack;22 23 };
复制代码

  具体实现代码为:

 stack.hpp

  Boost单元测试代码为:

 BoostUnitTest.cpp

   2.3 基于指针

  基于指针的栈也是在程序运行时才动态分配内存的。不过,它跟前两者不一样的是,它的内存利用效率高,不会存在内存浪费的问题。当然,这也就需要额外更多的内存申请及释放操作。

  栈模板类:

复制代码
 1 template<class T> 2 class Node 3 { 4 public: 5     T data; 6     Node * next; 7 }; 8  9 template<class T>10 class Stack11 {12 public:13     typedef Node<T> * NodePointer;14 15 public:16     Stack();17     virtual ~Stack();18     Stack(const Stack& orig);    // 拷贝构造函数19     Stack& operator=(const Stack& orig);    // 赋值运算符重载20     bool isEmpty();21     bool push(T val);       // 进栈。若栈不满,则将元素插入栈顶。22     T top();                // 取栈顶元素。若栈S非空,则返回栈顶元素,但不改变栈的状态。23     bool pop();             // 退栈。若栈非空,则将栈顶元素删去,并返回是否退栈成功的标志。24                             // 这里没有采用返回被删栈顶元素的原因在于这里写的是一个模板,25                             // 当栈为空的时候不方便返回。当然,这个问题是可以通过断言或26                             // 抛异常来解决的。具体做法可根据具体情况来定。27     int getSizeOfStack();28 29 private:30     NodePointer stack;31 32 };
复制代码

  具体实现代码为:

 stack.hpp

  Boost单元测试代码为:

 BoostUnitTest.cpp

 

  本篇博文的代码均托管到Taocode : http://code.taobao.org/p/datastructureandalgorithm/src/.

0 0