栈的三种实现(静态数组、动态数组及指针)
来源:互联网 发布:成都好吃网络的蛋糕店 编辑:程序博客网 时间: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 };
具体实现代码为:
Boost单元测试代码为:
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 };
具体实现代码为:
Boost单元测试代码为:
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 };
具体实现代码为:
Boost单元测试代码为:
本篇博文的代码均托管到Taocode : http://code.taobao.org/p/datastructureandalgorithm/src/.
- 栈的三种实现(静态数组、动态数组及指针)
- 基础知识--数组、栈、队列的静态、动态和链式实现
- 动态数组(指针)
- 二维数组的五种指针表示及指针数组
- 数组指针及指针数组的区别
- 函数的返回值问题(返回指针和数组的区别)静态存储区、动态数据区、栈
- 动态数组的实现 及 迭代器
- 基于二级指针实现动态二维数组的不定长输入及遍历
- 指针数组,数组指针,二维数组的动态内存分配
- 静态数组与动态数组的区别
- 动态数组的使用(动态分配,指针)
- 动态数组(栈)的实现实例
- 栈的动态数组实现
- 数组<->指针<->动态数组之间的关系
- 数组<->指针<->动态数组之间的关系
- 定义数组指针的三种方法
- 数组指针定义的三种方法
- 数组指针的三种定义形式
- Supporting Files里面的Info.plist
- jersey(一)
- keystore
- JavaScript的数据类型之Number, String, Boolean和Object
- ReportStudio进阶教程(二十二) - 单击表头进行排序
- 栈的三种实现(静态数组、动态数组及指针)
- 二叉堆的实现
- domion简单实用demo
- Android中View的绘制过程 onMeasure方法简述 附有自定义View例子
- 解决DataGridView在多线程中无法显示滚动条的问题
- c++语言笔记(1):vector
- 关于代码格式化工具astyle
- 手把手教你写Linux I2C设备驱动
- 双调数组查找(Bitonic search)