前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >请问你知道什么是栈吗?

请问你知道什么是栈吗?

作者头像
Java学习
发布于 2018-04-18 07:41:33
发布于 2018-04-18 07:41:33
97100
代码可运行
举报
文章被收录于专栏:java学习java学习
运行总次数:0
代码可运行

1.1栈的概念及记本操作

栈(stack)又称堆栈,是限制在表的一端进行插入和删除的线性表。其限制是仅允许在表的一端进行插入和删除操作,不允许在其他任何位置进行插入、查找、删除等操作。表中进行插入、删除操作的一端称为栈顶(Top),栈顶保存的元素称为栈顶元素。相对的,表的另一端称为栈底( Bottom)。当栈中没有数据元素时称为空栈;向一个栈插入元素又称为进栈或入栈;从一个栈中删除元素又称为出栈或退栈。

由于栈的插入和删除操作仅在栈顶进行,后进栈的元素必定先出栈,所以又把堆栈称为后进先出表( Last In First Out,LIFO)。图3.1显示了一个堆栈及数据元素插入和删除的过程。

在图3.1中,当ABCD 均已人栈之后,出栈时得到的序列为DCBA,这就是“后进先出”。在解决实际问题时,如果碰到了数据的使用具有“后进先出”的特性,就预示着可以使用堆栈来存储和使用这些数据,堆栈的基本操作除了进栈、出栈操作外,还有判空、取栈顶元素等操作。

1.2顺序栈

由于栈是运算受限的线性表,除了操作不同外,线性表的存储结构对栈也是适用的。利用顺序存储方式实现的栈称为顺序栈。为了便于理解,后面示例中顺序栈操作,均以学号和姓名为数据元素。

1.入职操作思想

根据顺序栈的存储特点,要将某一元素压入栈内,则要进行如下操作:

(1)先判断栈是否已经装满元素,如果未装满才能进行入栈操作,否则不操作。

(2 )栈顶指针先自增,给需要进栈的元素腾出内存空间。

(3 )再将要入栈的元素放入腾出的内存空间里,就是把入栈的元素赋值给对应的数组元素。

【例3.1】 1200101班已有2 名同学王丽、张阳的报到信息存放在栈内,现有(120010131,郑克龙) 同学来报到,请将其信息压人栈中。

首先要定义学生信息类来存放学生记录,具体参数自己定义。

接下来压入对应结点的过程如下:

栈顶指针先自增,给需要进栈的元素腾出内存空间,再往空间里压入元素( 120010131,郑克龙),如图3.3 所示。

2.入栈操作流程图

顺序栈的学生元素存放在data 数组中,length为栈的总长度,top为栈顶指针,则学生元素入栈程序流程图如图3.4 所示。

3.入栈操作代码实现

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class SeqStack { //顺序栈
 //在该例中各元素为学生对象,因此数组定义为student类型
    Student data[];//data为存放学生表各数据元素的数组
    int length;//栈长度
    int top;//栈顶指针
public SeqStack(){
     data=new Student[35];
     length=35;
     top=-1;
   }
public boolean push(Student stu){
     boolean bRst=false;
     if(top>=-1&&top<length-1){ //入栈位置正确与否判断
       top++;
       data[top]=stu;//插入新节点stu
       System.out.println("入栈:"+data[top].no+""+data[top].name);
       bRst=true;
     }
     return bRst;
   }
   public static void main(String[] args) {
     Student stu1=new Student();
     stu1.no="120010103";
     stu1.name="张阳";
     Student stu2=new Student();
     stu2.no="120010102";
     stu2.name="王丽";
     Student stu3=new Student();
     stu3.no="120010131";
     stu3.name="郑克龙";
     SeqStack ss= new SeqStack();
     ss.push(stu1);
     ss.push(stu2);
     ss.push(stu3);
   }
}

4.出栈操作思想

根据顺序栈的存储特点,要取出栈内某一元素,则要进行如下操作:

(1) 先判断栈是否有元素,如果有元素时才能进行出栈操作,否则不操作。

(2 )再将要出栈的元素取出放在内存空间里。

(3 )栈顶指针自减。

【例3.2】1200101班已有3名同学王丽、张阳、郑克龙的报到信息存放在栈内,现需要从栈中取出一位同学的信息进行审查,并显示取出的信息。

首先要定义学生信息类来存放学生记录,具体参见上一章的class Student 定义。

接下来取出对应结点的过程如下:

出栈前如图3.5 所示。

先把需要出栈的元素( 120010131,郑克龙)取出放在内存空间里,再把栈顶指针自减如图3.6 所示。

5.出栈操作流程图

顺序栈的学生元素存放在data数组中,length为栈的总长度,top为栈顶指针,则学生元素出栈流程图如3.7所示。

6.出栈操作代码实现

在入栈的基础上,添加出栈代码,实现如图3.7的流程功能,具体代码实现如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class SeqStack { // 顺序栈
  // 在该例中各元素为学生对象,因此数组定义为student类型
  Student data[];// data为存放学生表各数据元素的数组
  int length;// 栈长度
  int top;// 栈顶指针
  public SeqStack() {
    data = new Student[35];
    length = 35;
    top = -1;
  }
  // 进栈
  public boolean push(Student stu) {
    boolean bRst = false;
    if (top >= -1 && top < length - 1) { // 入栈位置正确与否判断
      top++;
      data[top] = stu;// 插入新节点stu
      System.out.println("入栈:" + data[top].no + "" + data[top].name);
      bRst = true;
    }
    return bRst;
  }
  // 出栈
  public Student pop() {
    Student stu = null;
    if (top >= 0 && top < length) {
      stu = data[top];
      System.out.println("出栈:" + data[top].no + "" + data[top].name);
      top--;
    }
    return stu;
  }
  public static void main(String[] args) {
    Student stu1 = new Student();
    stu1.no = "120010103";
    stu1.name = "张阳";
    Student stu2 = new Student();
    stu2.no = "120010102";
    stu2.name = "王丽";
    Student stu3 = new Student();
    stu3.no = "120010131";
    stu3.name = "郑克龙";
    SeqStack ss = new SeqStack();
    ss.push(stu1);
    ss.push(stu2);
    ss.push(stu3);
    //出栈
    while(ss.top>=0){
      ss.pop();
    }
  }
}

1.3链栈

用链式存储结构实现的栈称为链栈。其结点结构与单链表的结构相同,链式堆栈也是由一个个结点组成的,每个结点由两个域组成,一个是存放数据元素的数据元素域element,另一个是存放指向下一个结点的对象引用(即指针)next

因为栈中的主要运算是在栈顶插入、删除,显然在链表的头部做栈顶是最方便的,而且没有必要像单链表那样为了运算方便附加一个头结点,所以链式堆栈通常不带头结点。

通常将链栈表示成图3.8 的形式。

在学生信息类的基础上,链栈的结点定义如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class Node { // 节点类
  public Student stu; // 节点数据为学生对象
  public Node next;// 后继节点的地址
  public Node() {
    stu = null;
    next = null;
  }
}

链栈的基本操作也是进栈和出栈操作。

1.进栈操作思想

根据链栈的存储特点,要将某一个新节点s压入栈内,则要进行如下操作:

(1) 处理新结点s的后继,这个后继就是原本的栈顶结点。

(2) 将栈顶指针top 重新指向新结点s即可。

【例3.3】1200101班已有两名同学王丽、张阳的报到信息存放在链栈内,现有(120010131,郑克龙) 同学来报到,请将其信息压人链栈中。

首先要定义学生信息类和结点类。

接下来将对应结点压人链栈内的过程如下:

入栈前如图3.9 所示。

生成新节点(120010131,郑克龙),处理新节点的后继,使其后继指向原本的栈顶节点,如图3.10所示。

将栈顶指针top重新指向新节点(120010131,郑克龙)即可,如果3.11所示。

2.进栈操作流程图

链栈中插入的学生元素存放在node中,top为栈顶指针,curlen为栈的长度,则学生元素入栈程序流程图如图3.12所示。

3.进栈操作代码实现

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class LinkStack {// 链栈
  Node top;// 链表头指针
  int curlen;// 实际表长

  public LinkStack() {
    top = null;
    curlen = 0;
  }

  // 在表的第i个位置前插入新数据元素node,返回插入操作结果
  public void push(Node node) {
    node.next = top;
    top = node;
    System.out.println("入栈" + top.stu.no + "" + top.stu.name);
    curlen++;
  }

  public static void main(String[] args) {
    LinkStack ls = new LinkStack();
    Node node1 = new Node();
    node1.stu = new Student();
    node1.stu.no = "120010103";
    node1.stu.name = "张阳";
    Node node2 = new Node();
    node2.stu = new Student();
    node2.stu.no = "120010102";
    node2.stu.name = "王丽";
    Node node3 = new Node();
    node3.stu = new Student();
    node3.stu.no = "120010131";
    node3.stu.name = "郑克龙";
    ls.push(node1);
    ls.push(node2);
    ls.push(node3);
  }

}

4.出栈操作思想

根据链栈的存储特点,要弹出某一个结点,则要进行如下操作:

(1) 在栈顶指针top 非空的情况下,保存弹出结点。

(2) 将栈顶指针top 下移一个元素,即top= top.next。

【例3.4】 1200101班已有3 名同学王丽、张阳、郑克龙的报到信息存放在链栈内,现需要从链栈中取出一位同学的信息进行审查,并显示取出的信息。

首先要定义学生信息类和结点类,具体参见上一章class Student 和class Node的定义。

接下来弹出对应结点的过程如图3.13 所示。

5.出栈操作流程图

链栈中弹出学生元素存放在ni中,top为栈顶指针,curlen为栈的长度,则学生元素出栈程序流程图如3.14所示。

6.出栈操作代码实现

在链表入栈程序的基础上,添加出栈代码,如图。3.14所示的流程功能,具体实现代码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class LinkStack {// 链栈
  Node top;// 链表头指针
  int curlen;// 实际表长

  public LinkStack() {
    top = null;
    curlen = 0;
  }

  // 在表的第i个位置前插入新数据元素node,返回插入操作结果
  public void push(Node node) {
    node.next = top;
    top = node;
    System.out.println("入栈" + top.stu.no + "" + top.stu.name);
    curlen++;
  }

  // ========出栈===========
  public Node pop() {
    Node ni = null;
    if (top != null) {
      ni = top;
      top = top.next;
      curlen--;
      System.out.println("出栈" + ni.stu.no + "" + ni.stu.name);
    }
    return ni;

  }

  public static void main(String[] args) {
    LinkStack ls = new LinkStack();
    Node node1 = new Node();
    node1.stu = new Student();
    node1.stu.no = "120010103";
    node1.stu.name = "张阳";
    Node node2 = new Node();
    node2.stu = new Student();
    node2.stu.no = "120010102";
    node2.stu.name = "王丽";
    Node node3 = new Node();
    node3.stu = new Student();
    node3.stu.no = "120010131";
    node3.stu.name = "郑克龙";
    ls.push(node1);
    ls.push(node2);
    ls.push(node3);
    // =======出栈==========
    while (ls.top != null) {
      ls.pop();
    }
  }

}
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2018-01-31,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 java学习 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
腾讯云搭建Socks5多IP代理服务器实现游戏单窗口单IP完美搭建教程附带工具「建议收藏」
https://cloud.tencent.com/document/product/1199/41648#eip-.E9.85.8D.E9.A2.9D.E9.99.90.E5.88.B6
全栈程序员站长
2022/06/25
34K3
腾讯云搭建Socks5多IP代理服务器实现游戏单窗口单IP完美搭建教程附带工具「建议收藏」
腾讯云服务器免费更换公网IP的方法 一天更换三次
前几天老蒋有分享到如果我们选择的腾讯云服务器需要更换公网IP地址可以通过购买弹性IP地址来切换,但是这个是需要费用的,不过如果我们将IP地址用到服务器中是不会扣费,只有闲置的时候才会计费(腾讯云申请弹性公网IP及绑定腾讯云服务器教程)。如果我们并不是需要特别多的公网IP进行切换,其实可以利用腾讯云服务器自带的更换公网IP的方式切换IP。
老蒋
2021/12/27
9.6K0
腾讯云服务器免费更换公网IP的方法 一天更换三次
腾讯云轻量云服务器的那些优缺点和不足盘点
其实这个腾讯云的轻量应用服务器,它的优点或者说它的优势还是很多的,比如说它的价格便宜,性价比高,对于我们这些入门级的用户,个人用户,个人开发者,或者说学生多学习开发等等,这些用途的需求的话,其实完全是可以满足的。
wordpress建站吧
2022/03/16
5.5K0
怎么更换腾讯云的弹性公网IP
在实例的管理页面,选择待转换 IP 的云服务器地域,并在对应云服务器所在行,单击更多 > IP/网卡 > 更换公网 IP。
群联云安全小杜
2024/11/01
2.1K1
怎么更换腾讯云的弹性公网IP
【玩转腾讯云】腾讯云服务器bt宝塔配置弹性网卡实现多个公网ip
独立ip的优点,在这里就不多赘述了。而网上关于这方面的帖子大多都很朦统,今天写一下避免各位在走我走过的坑。也方便自己日后查看。
AlexTao
2020/04/22
54.2K20
【玩转腾讯云】腾讯云服务器bt宝塔配置弹性网卡实现多个公网ip
腾讯云服务器利用弹性公网IP为服务器更换动态IP和固定IP
一般情况下,无论我们购买哪家的VPS、云服务器产品都是有一个公网固定IP地址的,当然也有服务商不提供公网IP(前几天VULTR商家推出系列2.5美元方案但是都没有IPV4)。有些时候特殊项目的需要,我们需要服务器IP地址变化,或者需要将服务器更换IP地址,不同的商家有不同的操作方法,当然也有商家是不可以操作的只能重新购买服务器才有不同/新的IP。
2019/05/10
28K0
手把手教学!教你3步高效配置云服务器(windows/Linux版)
如果你是首次使用云服务器,建议你先选择轻量应用服务器(Lighthouse) 来作为云服务器使用的入门途径。
腾讯产业互联网学堂1
2023/09/04
9600
手把手教学!教你3步高效配置云服务器(windows/Linux版)
给一台腾讯云服务器配上多个免费外网弹性IP
https://cloud.tencent.com/document/product/213/15379#.E7.BD.91.E5.8D.A1.E7.9B.B8.E5.85.B3.E9.99.90.E5.88.B6
Cong Min
2019/03/10
12.4K0
腾讯云轻量应用服务器和CVM云服务器有什么区别?
腾讯云轻量服务器和云服务器有什么区别?为什么轻量应用服务器价格便宜?是因为轻量服务器CPU内存性能比云服务器CVM性能差吗?轻量应用服务器适合中小企业或个人开发者搭建企业官网、博客论坛、微信小程序或开发测试环境,云服务器CVM适合更复杂如高并发网站、大数据计算、机器学习等复杂应用场景。轻量服务器网从性能测试、网络带宽、计费价格、应用搭建及适合用户等方面来详细说明腾讯云轻量应用服务器和云服务器CVM区别:
上云小秘书
2023/04/10
9.8K0
腾讯云轻量应用服务器和CVM云服务器有什么区别?
腾讯云服务器建站系列 - 腾讯云CVM选择以及系统安装篇
老蒋前天遇到一个比较小白的网友,估计之前从来没有建站过,然后不懂为何还购买了腾讯云服务器。而且,服务器中什么都没有安装,只是在本地电脑中可以打开PHPSTUDY测试环境搭建的网站,问怎么无法打开域名直接打开服务器的。看到这样的问题,比当初问在服务器直接主域名绑定域名就想打开网站的网友更深不可测。
老蒋
2021/12/27
10.2K0
腾讯云服务器建站系列 - 腾讯云CVM选择以及系统安装篇
腾讯云服务器bt宝塔配置弹性网卡实现多个公网ip
独立ip的优点,在这里就不多赘述了。而网上关于这方面的帖子大多都很朦统,今天写一下避免各位在走我走过的坑。也方便自己日后查看。
AlexTao
2019/09/05
17K0
腾讯云服务器bt宝塔配置弹性网卡实现多个公网ip
新手必看!云服务器避坑指南
刚接触云服务器时,面对“安全组”“弹性IP”等术语,新手常像踏入迷宫。为何本地运行顺畅的程序上云后连基础连接都困难?本文用最直白的语言,拆解云服务器的核心规则,帮你避开那些老手踩过的坑。
秋月叶落
2025/05/27
1140
新手必看!云服务器避坑指南
【腾讯云负载均衡CLB】跨地域绑定2.0(新版)IDC-IP最佳实践!
负载均衡(CLB)支持通过云联网,跨地域绑定云服务器,允许客户选取多个后端云服务器的地域,跨 VPC、跨地域绑定后端云服务器,(支持IDC线下IP)。 目前该功能处于内测阶段,如果您需要体验该功能,境内跨地域绑定请通过 内测申请,境外跨地域绑定请进行 商务申请。 特别说明: 跨地域互联绑定云服务器暂不支持传统型负载均衡 该功能仅标准账户类型支持。若您无法确定账户类型,请参见 判断账户类型。 跨地域绑定2.0和混合云部署,不支持 安全组默认放通,请在后端服务器上放通 Client IP 和服务端口。 跨地域互
TCS-F
2021/11/01
3.6K0
【腾讯云负载均衡CLB】跨地域绑定2.0(新版)IDC-IP最佳实践!
玩转腾讯云-云上网络实操
本文带大家一起通过实操方式来学习腾讯云私有网络管理,通过弹性公网IP、NAT网关访问Internet,通过安全组、ACL进行网络访问控制。对等连接、云联网实现跨地域网络访问等网络互联实操请参阅:玩转腾讯云-网络互联实操。
hsp
2022/05/15
8.7K0
腾讯云轻量应用服务器分配唯一的独立的公网IP地址吗?
是的,​腾讯云轻量应用服务器默认会分配一个独立的公网IPv4地址,且该IP地址为独享​,你一个人使用的(非共享IP),用户可完全自主使用。以下是关键细节解析:
用户11543454
2025/04/02
4610
腾讯云弹性网卡产品使用介绍
最近有个网友在问腾讯云主机的公网IP总在变为什么不能固定下来。 经过了解此用户是购买腾讯云主机用于测试和临时搭建网站,所以计费方式是“按量计费”和“竞价实例” 当云主机重启时就会出现网友反馈的问题公网IP会变化,那是否有方法让公网IP不变? 这里推荐两种方式:
研究僧
2020/05/30
7.8K0
弹性公网ip可以绑定家里的服务器吗 弹性公网ip和固定ip的差别
弹性公网在购买之后会分配到一个 ip地址,等有了这个地址之后,就可以开始使用了。作为一个地区的公网ip,如果想通过云服务配置,绑定家里的服务器可行不可行。那么弹性公网ip可以绑定家里的服务器吗?下面给大家在下面做一个简单的介绍。
用户8715145
2021/10/15
15.9K0
7天学会腾讯云服务器建站(四) – 腾讯云服务器面板常用功能熟悉
通过前面三篇腾讯云服务器建站教程,我们能快速的学会选择腾讯云服务器,安装常用的宝塔面板,可视化进行建站和管理网站的基本的功能。其实到目前为止,我们只需要三天时间就能学会利用腾讯云服务器建站,但是为什么我们还需要设置7天学会系列呢?因为还有一些细节需要我们加深巩固的,这样使得我们知道一些常规的操作技巧和功能。
老蒋
2019/04/29
6.7K0
腾讯云公网三网静态最佳实践方案
公网三网(电信,联通,移动)静态资源强依赖于运营商架构冗余,腾讯云无法支持等同于BGP的跨可用区调度操作,因此三网故障时无法快速通过调度实现业务恢复,需要通过业务层的冗余部署和涉及实现故障期间的跨可用区或同可用区跨运营商的切换,切换期间访问品质会降低,但可以保证业务可用性。
张兴龙-leoxzhang
2020/10/23
5.2K0
云服务器多IP场景实践
弹性公网IP(Elastic IP,EIP)简称弹性IP地址或弹性IP,是可以独⽴申请的公⽹IP地址。EIP可以实时绑定/解绑到私有⽹网络的CVM、NAT网关、弹性网卡上。
WAF
2018/12/04
29K3
推荐阅读
相关推荐
腾讯云搭建Socks5多IP代理服务器实现游戏单窗口单IP完美搭建教程附带工具「建议收藏」
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档