栈是什么?如果用生活中最常见的例子,我想到是书本的放置(当然这是部分人喜欢的做法)。但是给人的感觉是非常直接的,书本整齐跨一叠在一起,放在最上面的那本最先拿走,放在最底下那本书就最后拿走,形象吧,生活中有很多后进先出的栗子,就不一一说明了,用图来说明应该很好理解。

放在最上面的那本书的位置叫栈顶,栈顶是可变的,比如说你拿走了西游记,那么栈顶就是红楼梦得位置。相对应的栈底是不可操作的一端。
栈是一种特殊的线性表,特殊之处在于只能在一端对其进行操作,把元素放到栈中,这操作叫压栈(push),压栈之后,栈顶指针就向上移动。把元素从栈顶弹出,这叫出栈(pop),出栈后栈顶指针向下移动。访问栈只能从栈顶元素进行。栈是很重要的数据结构,在很多算法都有应用,比如图的深度优先遍历算法(DFS),Dijkstra算法的中转站。

栈的实现分为两种,一是顺序栈,用数组来实现,二是链式栈,用指针将结点串联起来,与链表相似,但仅能在栈顶进行操作。

先实现简单的顺序栈,顺序栈简直不要太简单,上代码:

#ifndef STATICSTACK_H
#define STATICSTACK_Htemplate <typename T, int N>
class StaticStack
{protected:T array[N];   // 使用模板参数决定栈的大小int m_top;   // 使用整型作为标记,相当于栈顶指针int m_size;   // 栈中数据元素的个数
public:StaticStack()    // 初始化操作得做一下{m_top = -1;m_size = 0;}bool push(const T& obj)   // 压栈操作,就是往数组增加一个元素{bool ret = m_size < N;   // 满了就没办法了if( ret ){array[++m_top] = obj;++m_size;}return ret;}bool pop()  // 出栈操作{bool ret = m_size > 0;if( ret ){--m_top;--m_size;}return ret;}T top()   // 获取栈顶元素{return array[m_top];}void clear() // 把栈清空{m_top = -1;m_size = 0;}int size() // 获取栈的大小{return m_size;}~StaticStack(){clear();}
};#endif

来用一下这个简单顺序栈。记住,后进先出!

#include <iostream>
#include "StaticStack.h"using namespace std;int main(int argc, const char* argv[])
{StaticStack<int, 10> stack;for(int i = 0; i < 10; ++ i){stack.push(i);}// 入栈的时候是 0123456789 的顺序for(int i = 0; i < 10; ++ i){cout << stack.top() << endl;stack.pop();}return 0;
}

输出正确。OK,顺序栈就可以跳过了,因为顺序栈的实现依赖于原生数组,所以在定义的时候必须给定大小,并且在使用的过程中不能动态改变其大小,这是顺序栈的一个缺点,另外,当顺序栈存放的元素是类类型,那么在定义顺序栈时就会自动调用类的构造函数,有多少个元素就会调用多少次,这样做显然会降低效率,所以顺序栈的使用相对较少。

现在重点来实现链式栈吧,有了顺序栈的基础,实现链式栈也相当容易。
直接上代码:

#ifndef LINKSTACK_H
#define LINKSTACK_Htemplate <typename T>
class LinkStack
{protected:struct Node{T data;Node* next;};mutable Node header;  // 使用头节点会方便各种操作int m_size;public:LinkStack(){header.next = NULL;m_size = 0;}bool push(const T& obj)   // 压栈操作{bool ret = true;   Node* n = new Node();if( n != NULL ){n->data = obj;Node* current = &header;  // 相当于链表的头插n->next = current->next;current->next = n;++m_size;}else{ret = false;}return ret;}bool pop()   // 出栈操作{bool ret = true;if( m_size > 0 ){Node* current = &header;  // 相当于链表的头删Node* todel = current->next;current->next = todel->next;--m_size;delete todel;}else{ret = false;}return ret;}T top() const   // 获取栈顶元素{Node* current = header->next;return current->data;}int size() const{return m_size;}void clear()    // 清空栈{while( m_size > 0 ){pop();}}~LinkStack(){clear();}
};#endif

仅仅是实现一个栈好像没有什么好玩的,顺序栈操作一个数组,链式就几个指针操作。现在用栈来实现一个扫描函数,将字符串中的左右符号进行匹配。举个栗子,“( a { b c [ d < e " f ’ g’ " h > i ] j } k)”,这样一个看起来复杂l凌乱的字符串,怎么知道它的左右符号匹不匹配呢?人工智能嘛,人工来数一下不就可以了吗?Good idea!简单的数几分钟就应该知道结果了,要是一本书那么多的字符串怎么来数?当然是把工作交给计算机!写个程序来检查左右符号是否匹配不就得了。主要注意的地方是左符号、右符号以及引号的处理,其他字符直接忽略。知道重点了,实现就容易了,说干就干,动手!

#include <iostream>
#include "LinkStack.h"// 需要提前准备相应的辅助函数
bool is_Left(const char c)  // 判断是否为左符号
{return (c == '(') || (c == '{') || (c == '<') || (c == '[');
}bool is_Right(const char c)    // 判断是否为右符号
{   return (c == ')') || (c == '}') || (c == '>') || (c == ']');
}bool is_Quot(const char c) // 判断是否为引号
{return (c == '\'') || (c == '\"');
}bool is_Match(const char l,const char r)   // 进行匹配判断
{bool ret = ( (l == '(') && (r == ')') )   ||( (l == '{') && (r == '}') )   ||( (l == '[') && (r == ']') )   ||( (l == '<') && (r == '>') )   ||( (l == '\'') && (r == '\'') ) ||( (l == '\"') && (r == '\"') ) ;    return ret;
}bool scan_func(const char* str)    // 扫描字符串的函数
{bool ret = true;  int i = 0;str = str ? str : ""; // 参数合法性判断,如果参数为空,则用空字符串代替LinkStack<char> stack;    // 看着怎么使用栈吧while( ret && (str[i] != '\0') )  // 循环遍历字符串{                 // 如果有不匹配的字符就立即结束循环if( is_Left(str[i]) )        // 左符号,直接入栈{stack.push(str[i]);}else if( is_Right(str[i]) )  // 右符号,判断栈是否为空{              // 如果栈为空,结束循环if( (stack.size() > 0) && (is_Match(stack.top(), str[i])) )      {stack.pop();   // 栈不为空,且与栈顶元素能匹配,那就把栈顶中的左符号出栈}else{ret = false; }}else if( is_Quot(str[i]) )    // 引号判断{                // 如果栈为空或者与栈顶元素不匹配,入栈if( (stack.size() == 0) || (!is_Match(stack.top(), str[i])) ){stack.push(str[i]);}            // 与栈顶元素匹配,那就将栈顶的引号出栈else if( is_Match(stack.top(), str[i]) ){stack.pop();}}}return (ret && (stack.size() == 0) );
}int main(int argc, const char* argv[])
{const char* str1 = " < ( [ { 123 } ] ) > ";const char* str2 = " \" \' 123 \' \" ";const char* str3 = "< 123 ";cout << endl;cout << str1 << " result of match : " << ( scan_func(str1) ? " true " : " false " ) << endl;cout << endl;cout << str2 << " result of match : " << ( scan_func(str2) ? " true " : " false " ) << endl;cout << endl;cout << str3 << " result of match : " << ( scan_func(str3) ? " true " : " false " ) << endl;return 0;
}

看看输出结果,多easy,要是用人工的智能来数,得花点点点时间。

实现数据结构中的栈---后进先出LIFO相关推荐

  1. 初始化栈的代码_数据结构中的栈,你知道多少?

    由于栈比较简单,也很容易理解,学过的人都知道一句话就可以描述栈的特性:后进先出.所以这篇文章主要是写如何使用代码来描述栈,当然也是让大家很容易理解的语言.还是先给出这篇文章的大致脉络. 首先,对栈有一 ...

  2. 数据结构括号匹配代码_数据结构中的栈,你知道多少?

    由于栈比较简单,也很容易理解,学过的人都知道一句话就可以描述栈的特性:后进先出.所以这篇文章主要是写如何使用代码来描述栈,当然也是让大家很容易理解的语言.还是先给出这篇文章的大致脉络. 首先,对栈有一 ...

  3. 对数据结构中共享栈减少上溢的理解

    目录 共享栈的定义 为何使用共享栈 栈满 后记 共享栈的定义 简单说就是两栈共用一片连续内存空间. (王道书定义:)共享栈就是让两个顺序栈(一片连续内存,栈就是顺序栈)共享一个一维数组空间,将两个栈的 ...

  4. 数据结构中堆、栈和队列的理解

    一.堆 堆是一种经过排序的树形数据结构,每个节点都有一个值,通常我们所说的堆的数据结构是指二叉树.所以堆在数据结构中通常可以被看做是一棵树的数组对象.而且堆需要满足一下两个性质: (1)堆中某个节点的 ...

  5. c++数据结构中 顺序队列的队首队尾_用队列实现栈,用栈实现队列,听起来有点绕,都搞懂了就掌握了精髓

    一.背景 栈和队列是数据结构中最常用到的两种结构,有非常广泛的运用,该篇文章将通过动画的手段,展示栈和队列相互实现的底层原理,让我们真正搞懂栈和队列的特性. 二.概念 2.1 栈 栈[Stack]:是 ...

  6. 什么是内存中的堆和栈?与数据结构中的堆和栈有什么区别?

    内存中的堆和栈 一直使用堆和栈的相关概念,对内存中(操作系统)中的堆与栈和数据结构中的堆与栈一直不求甚解,这次,突然想起这个问题,在此进行一个简单梳理归纳,如有错误,恳请读者指出. 栈(stack) ...

  7. Kiner算法刷题记(十四):数据结构中的“渣男”——单调栈(数据结构基础篇)

    系列文章导引 系列文章导引 开源项目 本系列所有文章都将会收录到GitHub中统一收藏与管理,欢迎ISSUE和Star. GitHub传送门:Kiner算法算题记 知识回顾 我们之前讨论过单调队列,知 ...

  8. 堆(概念,数据结构中堆与内存堆区的区别 ,堆的基本操作)

    堆的特性: 必须是完全二叉树 用数组实现 任一结点的值是其子树所有结点的最大值或最小值 最大值时,称为"最大堆",也称大根堆: 在完全二叉树中,任何一个子树的最大值都在这个子树的根 ...

  9. 数据结构中堆栈和内存堆栈的区别

    最近接触数据结构中的堆栈,想到了初学Java时,关于新实例化或者定义一个对象时候,声明对象,对象的变量名存放在栈内存中,当我们手动new之后,就会在堆内存中开辟一个空间,用来存放变量地址值,并将变量地 ...

  10. 图解:数据结构中的6种「树」,柠檬问你心中有数吗?

    数据结构这门课程是计算机相关专业的基础课,数据结构指的是数据在计算机中的存储.组织方式. 我们在学习数据结构时候,会遇到各种各样的基础数据结构,比如堆栈.队列.数组.链表.树...这些基本的数据结构类 ...

最新文章

  1. Git(创建版本库)
  2. C# 版本 疫情传播仿真程序
  3. 使用HazelCast进行休眠缓存:基本配置
  4. 爬了知乎200万数据,图说程序员都喜欢去哪儿工作~
  5. pat1091. Acute Stroke (30)
  6. Java之设计模式一
  7. Delphi Sysem.JSON 链式写法(转全能中间件)
  8. 程序员简洁简历模板分享
  9. 计算机网络第四章课后答案(第七版谢希仁著)
  10. IEEE会议Latex模板下载教程
  11. itest听力答案2020_大学英语itest2018答案
  12. Java基础eclipse版(二)——JDK、Eclipse的下载与安装
  13. L1-007 念数字(C语言)
  14. Android传感器之陀螺仪传感器
  15. 小程序中纯CSS实现仿京东小优惠券图标
  16. CSS空格和换行的处理
  17. 3v stm32 供电 晶振起振_32.768kHz晶振不起振的终极解决方法?
  18. 智能大屏交互中心成彩电业新趋势
  19. 推算几天后的日期 —— 代码篇
  20. Chrome浏览器如何完美实现滚动截图技巧

热门文章

  1. ZYNQ BRAM_ctrl PS PL通信报错
  2. iOS SceneDelegate使用总结
  3. 华为手机流量日显示无服务器,华为手机开启了数据流量却不能上网怎么办
  4. oracle类型number,Oracle NUMBER 类型细讲
  5. 大数据是什么?大数据的定义?
  6. linkis标准版安装教程
  7. 读headFirst设计模式 - 装饰者模式
  8. elasticsearch启动报错:master not discovered yet
  9. 科海故事博览杂志科海故事博览杂志社科海故事博览编辑部2022年第15期目录
  10. 组建家庭计算机网络过程是怎么样的,如何组建完善的家庭无线网络操作步骤