0. 数据结构图文解析系列

数据结构系列文章
数据结构图文解析之:数组、单链表、双链表介绍及C++模板实现
数据结构图文解析之:栈的简介及C++模板实现
数据结构图文解析之:队列详解与C++模板实现
数据结构图文解析之:树的简介及二叉排序树C++模板实现.
数据结构图文解析之:AVL树详解及C++模板实现
数据结构图文解析之:二叉堆详解及C++模板实现
数据结构图文解析之:哈夫曼树与哈夫曼编码详解及C++模板实现

1. 栈的简介

1.1栈的特点

栈(Stack)是一种线性存储结构,它具有如下特点:

  1. 栈中的数据元素遵守”先进后出"(First In Last Out)的原则,简称FILO结构。
  2. 限定只能在栈顶进行插入和删除操作。

1.2栈的相关概念

栈的相关概念:

  1. 栈顶与栈底:允许元素插入与删除的一端称为栈顶,另一端称为栈底。
  2. 压栈:栈的插入操作,叫做进栈,也称压栈、入栈。
  3. 弹栈:栈的删除操作,也叫做出栈。

例如我们有一个存储整型元素的栈,我们依次压栈:{1,2,3}

在压栈的过程中,栈顶的位置一直在”向上“移动,而栈底是固定不变的。

如果我们要把栈中的元素弹出来:

出栈的顺序为3、2、1 ,顺序与入栈时相反,这就是所谓的”先入后出“。

在弹栈的过程中,栈顶位置一直在”向下“移动,而栈底一直保持不变。

如果你玩过一种称为汉诺塔的益智玩具,你就会知道游戏中小圆盘的存取就是一种先进后出的顺序,一个圆柱就是一个栈:

1.3 栈的操作

栈的常用操作为:

  1. 弹栈,通常命名为pop
  2. 压栈,通常命名为push
  3. 求栈的大小
  4. 判断栈是否为空
  5. 获取栈顶元素的值

1.4 栈的存储结构

栈既然是一种线性结构,就能够以数组或链表(单向链表、双向链表或循环链表)作为底层数据结构。

本文我们以数组、单向链表为底层数据结构构建栈。

2. 基于数组的栈实现

当以数组为底层数据结构时,通常以数组头为栈底,数组头到数组尾为栈顶的生长方向:

2.1 栈的抽象数据类型

栈提供了如上所述操作的相应接口。

  1. template<typename T>
  2. class ArrayStack
  3. {
  4. public:
  5. ArrayStack(int s = 10); //默认的栈容量为10
  6. ~ArrayStack();
  7. public:
  8. T top(); //获取栈顶元素
  9. void push(T t); //压栈操作
  10. T pop(); //弹栈操作
  11. bool isEmpty(); //判空操作
  12. int size(); //求栈的大小
  13. private:
  14. int count; //栈的元素数量
  15. int capacity; //栈的容量
  16. T * array; //底层为数组
  17. };
  1. count 为栈的元素数量,capacity为栈的容量,count<=capacity,当栈满的时候,count = capacity。
  2. 本实现中不支持栈的动态扩容,栈满的时候无法再插入元素。栈的容量在定义栈的时候就需要指定,默认的栈容量为10。

2.2 栈的具体实现

栈的实现还是相对简单的,很容易理解。这里就不再画蛇添足了。

  1. /*栈的判空操作*/
  2. template <typename T>
  3. bool ArrayStack<T>::isEmpty()
  4. {
  5. return count == 0; //栈元素为0时为栈空
  6. };
  7. /*返回栈的大小*/
  8. template <typename T>
  9. int ArrayStack<T>::size()
  10. {
  11. return count;
  12. };
  13. /*插入元素*/
  14. template <typename T>
  15. void ArrayStack<T>::push(T t)
  16. {
  17. if (count != capacity) //先判断是否栈满
  18. {
  19. array[count++] = t;
  20. }
  21. };
  22. /*弹栈*/
  23. template <typename T>
  24. T ArrayStack<T>::pop()
  25. {
  26. if (count != 0) //先判断是否是空栈
  27. {
  28. return array[--count];
  29. }
  30. };
  31. /*获取栈顶元素*/
  32. template <typename T>
  33. T ArrayStack<T>::top()
  34. {
  35. if (count != 0)
  36. {
  37. return array[count - 1];
  38. }
  39. };

2.3 栈的代码测试

  1. int _tmain(int argc, _TCHAR* argv[])
  2. {
  3. ArrayStack <int> p(5);
  4. for (int i = 0; i < 5; i++)
  5. {
  6. p.push(i);
  7. }
  8. cout << "栈的大小:"<<p.size() << endl;
  9. cout << "栈是否为空:"<<p.isEmpty() << endl;
  10. cout << "栈顶元素:"<<p.top() << endl;
  11. cout << "依次出栈:" << endl;
  12. while (!p.isEmpty())
  13. {
  14. cout << p.pop() << endl;
  15. }
  16. getchar();
  17. return 0;
  18. }

测试结果:

  1. 栈的大小:5
  2. 栈是否为空:0
  3. 栈顶元素:4
  4. 依次出栈:
  5. 4
  6. 3
  7. 2
  8. 1
  9. 0

3. 基于单链表的栈

以链表为底层的数据结构时,以链表头为作为栈顶较为合适,这样方便节点的插入与删除。压栈产生的新节点将一直出现在链表的头部;

3.1 链表节点

  1. /*链表节点结构*/
  2. template <typename T>
  3. struct Node
  4. {
  5. Node(T t) :value(t), next(nullptr){};
  6. Node() :next(nullptr){};
  7. public:
  8. T value;
  9. Node<T>* next;
  10. };
  1. value:栈中元素的值
  2. next:链表节点指针,指向直接后继

3.2 栈的抽象数据类型

基于链表的栈提供的接口与基于数组的栈一致。


  1. /*栈的抽象数据结构*/
  2. template <typename T>
  3. class LinkStack
  4. {
  5. public:
  6. LinkStack();
  7. ~LinkStack();
  8. public:
  9. bool isEmpty();
  10. int size();
  11. void push(T t);
  12. T pop();
  13. T top();
  14. private:
  15. Node<T>* phead;
  16. int count;
  17. };

3.3 栈的具体实现

  1. /*返回栈的大小*/
  2. template <typename T>
  3. int LinkStack<T>::size()
  4. {
  5. return count;
  6. };
  7. /*栈的判空操作*/
  8. template <typename T>
  9. bool LinkStack<T>::isEmpty()
  10. {
  11. return count == 0;
  12. };
  13. /*插入元素*/
  14. template<typename T>
  15. void LinkStack<T>::push(T t)
  16. {
  17. Node <T> *pnode = new Node<T>(t);
  18. pnode->next = phead->next;
  19. phead->next = pnode;
  20. count++;
  21. };
  22. /*弹栈*/
  23. template <typename T>
  24. T LinkStack<T>::pop()
  25. {
  26. if (phead->next != nullptr) //栈空判断
  27. {
  28. Node<T>* pdel = phead->next;
  29. phead->next = phead->next->next;
  30. T value = pdel->value;
  31. delete pdel;
  32. count--;
  33. return value;
  34. }
  35. };
  36. /*获取栈顶元素*/
  37. template <typename T>
  38. T LinkStack<T>::top()
  39. {
  40. if (phead->next!=nullptr)
  41. return phead->next->value;
  42. };

3.4 栈的代码测试

  1. int _tmain(int argc, _TCHAR* argv[])
  2. {
  3. LinkStack <string> lstack;
  4. lstack.push("hello");
  5. lstack.push("to");
  6. lstack.push("you!");
  7. cout << "栈的大小:" << lstack.size() << endl;
  8. cout <<"栈顶元素:"<< lstack.top() << endl;
  9. while (!lstack.isEmpty())
  10. {
  11. lstack.pop();
  12. }
  13. cout << "栈的大小:" << lstack.size() << endl;
  14. getchar();
  15. return 0;
  16. }

测试结果:

  1. 栈的大小:3
  2. 栈顶元素:you
  3. 栈的大小:0

4. 栈的完整代码

基于数组的栈: https://github.com/huanzheWu/Data-Structure/blob/master/Stack/Main/Main/ArrayStack.h

基于单链表的栈:https://github.com/huanzheWu/Data-Structure/blob/master/singleList/singleList/singleList.h

原创文章,转载请注明出处:http://www.cnblogs.com/QG-whz/p/5170418.html

数据结构图文解析之:栈的简介及C++模板实现的更多相关文章

  1. 数据结构图文解析之:树的简介及二叉排序树C++模板实现.

    0. 数据结构图文解析系列 数据结构系列文章 数据结构图文解析之:数组.单链表.双链表介绍及C++模板实现 数据结构图文解析之:栈的简介及C++模板实现 数据结构图文解析之:队列详解与C++模板实现 ...

  2. 数据结构图文解析之:直接插入排序及其优化(二分插入排序)解析及C++实现

    0. 数据结构图文解析系列 数据结构系列文章 数据结构图文解析之:数组.单链表.双链表介绍及C++模板实现 数据结构图文解析之:栈的简介及C++模板实现 数据结构图文解析之:队列详解与C++模板实现 ...

  3. 数据结构图文解析之:数组、单链表、双链表介绍及C++模板实现

    0. 数据结构图文解析系列 数据结构系列文章 数据结构图文解析之:数组.单链表.双链表介绍及C++模板实现 数据结构图文解析之:栈的简介及C++模板实现 数据结构图文解析之:队列详解与C++模板实现 ...

  4. 数据结构图文解析之:队列详解与C++模板实现

    0. 数据结构图文解析系列 数据结构系列文章 数据结构图文解析之:数组.单链表.双链表介绍及C++模板实现 数据结构图文解析之:栈的简介及C++模板实现 数据结构图文解析之:队列详解与C++模板实现 ...

  5. 数据结构图文解析之:AVL树详解及C++模板实现

    0. 数据结构图文解析系列 数据结构系列文章 数据结构图文解析之:数组.单链表.双链表介绍及C++模板实现 数据结构图文解析之:栈的简介及C++模板实现 数据结构图文解析之:队列详解与C++模板实现 ...

  6. 数据结构图文解析之:二叉堆详解及C++模板实现

    0. 数据结构图文解析系列 数据结构系列文章 数据结构图文解析之:数组.单链表.双链表介绍及C++模板实现 数据结构图文解析之:栈的简介及C++模板实现 数据结构图文解析之:队列详解与C++模板实现 ...

  7. 数据结构图文解析之:哈夫曼树与哈夫曼编码详解及C++模板实现

    0. 数据结构图文解析系列 数据结构系列文章 数据结构图文解析之:数组.单链表.双链表介绍及C++模板实现 数据结构图文解析之:栈的简介及C++模板实现 数据结构图文解析之:队列详解与C++模板实现 ...

  8. 面试必备:高频算法题终章「图文解析 + 范例代码」之 矩阵 二进制 + 位运算 + LRU 合集

    Attention 秋招接近尾声,我总结了 牛客.WanAndroid 上,有关笔试面经的帖子中出现的算法题,结合往年考题写了这一系列文章,所有文章均与 LeetCode 进行核对.测试.欢迎食用 本 ...

  9. 二叉查找树(一)之 图文解析 和 C语言的实现

    概要 本章先对二叉树的相关理论知识进行介绍,然后给出C语言的详细实现.关于二叉树的学习,需要说明的是:它并不难,不仅不难,而且它非常简单.初次接触树的时候,我也觉得它似乎很难:而之所产生这种感觉主要是 ...

随机推荐

  1. org.hibernate.HibernateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here

    org.hibernate.HibernateException: No Hibernate Session bound to thread, and configuration does not a ...

  2. PacificA中的租约与失效检测解读

    PacificA是微软的在基于log的分布式存储系统中的复制技术. 由于配置管理器维护着当前配置的真实情况,因此主节点不必保持不变. 这是因为配置的本地视图在不同服务器上是不必同步的. 特别是,我们必 ...

  3. 机器学习实战笔记(Python实现)-01-K近邻算法(KNN)

    --------------------------------------------------------------------------------------- 本系列文章为<机器 ...

  4. 《java JDK7 学习笔记》之类和对象

    1.在java中,要产生对象必须先定义类,类是对象的设计图,对象是类的实例.类定义时使用class关键词,建立实例对象要使用new关键词.以类名声明的变量,称为参考名称.参考变量或直接叫参考. 2.想 ...

  5. 记录sql语句的执行记录,用于分析

    SET STATISTICS PROFILE ONSET STATISTICS IO ONSET STATISTICS TIME ONGO --这之间是要执行的脚本select * from [Use ...

  6. python基础(八)面向对象的基本概念

    作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 谢谢逆水寒龙,topmad和Liqing纠错 Python使用类(class)和对 ...

  7. Python字符串str的方法使用

    #!usr/bin/env python# -*-coding:utf-8-*-#字符串通常用双引号或单引号来表示:'123',"abc","字符串"#str字 ...

  8. ubuntu下安装lrzsz

    secureCRT中可以使用rz和sz命令上传和下载文件,可是这要linux中安装了lrzsz才可以.我用的时候无法使用apt-get自动安装,下面介绍手动安装的方法. 1 下载lrzsz软件  ht ...

  9. TCP通信丢包原因总结

    今天在公司问老大,公司的项目底层,是使用的TCP,因为可靠,自动断线重连,在底层都实现了,但是我记得TCP也会有掉包的问题,所以这文章就诞生了——关于TCP掉包的问题,TCP是基于不可靠的网络实现可靠 ...

  10. Shell基础学习小结

    0 shell基础概念 Shell是解释性语言,使用脚本编程语言的好处是,它们多半运行在比编译型语言还高的层级,能够轻易处理文件与目录之类的对象:缺点是它们的效率通常不如编译型语言.Shell命令有本 ...