什么是栈结构

栈结构是从数据的运算来分类的,也就是说栈结构具有特殊的运算规则,即:后进先出。

我们可以把栈理解成一个大仓库,放在仓库门口(栈顶)的货物会优先被取出,然后再取出里面的货物。

而从数据的逻辑结构来看,栈结构起始就是一种线性结构。

如果从数据的存储结构来进一步划分,栈结构包括两类:

顺序栈结构:

即使用一组地址连续的内存单元依次保存栈中的数据。在程序中,可以定义一个指定大小的结构数组来作为栈,序号为0的元素就是栈低,再定义一个变量top保存栈顶的序号即可。

链式栈结构:

即使用链表的的形式保存栈中各元素的值。链表首部(head指针所指向元素)为栈顶,链表尾部(指向地址为NULL)为栈底。

在栈结构中只能在一端进行操作,该操作端称为栈顶,另一端称为栈底。也就是说,保存和取出的数据都只能从栈结构的一端进行。从数据的运算角度来分析,栈结构是按照“后进先出”的原则处理结点数据的。

在栈结构中,只有栈顶元素是可以访问的,栈结构的数据运算也是非常简单。一般栈结构的基本操作只有两个:

入栈(Push):将数据保存到栈顶的操作。进行入栈操作前,先修改栈顶指针,使其向上移一个元素位置,然后将数据保存到栈顶指针所指的位置。

出栈(Pop):将栈顶数据弹出的操作。通过修改栈顶指针,使其指向栈中的下一个元素。

接下来,我们使用C++语言建立顺序栈,并完成顺序栈结构的基本运算

准备数据

准备在栈操作中需要用到的变量及数据结构等。

#define MAXLEN 50
struct DATA
{
string name;
int age;
};
struct StackType
{
DATA data[MAXLEN+1];
int top;
};

定义栈结构的长度MAXLEN,栈结构的数据元素类型DATA,以及栈结构的数据结构StackType。在数据结构StackType中,data为数据元素,top为栈顶的序号。当top=0时,表示栈为空,当top=MAXLEN时表示栈满。

数组元素都是充下标0开始的,这里为了讲述和理解方便,我们从下标1开始记录数据结点,下标0的位置不用。

初始化栈结构

在使用栈结构之前,首先需要创建一个空的顺序栈,也就是初始化顺序栈。顺序栈的初始化操作如下:

(1)按照符号常量MAXLEN指定大小申请一片内存空间,用来保存栈中的数据

(2)设置栈顶指针的值为0,表示一个空栈。

示例代码如下:

StackType *STInit()
{
StackType *p;
if(p=new StackType) //申请栈空间
{
p->top=0; //设置栈顶为0
return p; //返回栈顶指针
}
return NULL;
}

首先用new申请内存,然后设置栈顶为0,然后返回申请内存的首地址,申请失败返回NULL;

判断空栈

判断栈结构是否为空,如果是空栈,则表示该栈结构中没有数据,此时可以进行入栈操作,但是不可以进行出栈操作。

示例代码如下:

int STIsEmpty(StackType *s)
{
int t;
t=(s->top==0); //通过栈顶的值进行判断
return t;
}

输入参数s为一个指向操作的栈的指针。根据栈顶指针top判断是否为0,判断栈是否为空。

判断满栈

判断栈结构是否为满。如果是满栈,则表示该栈结构中没有多余的空间来保存额外数据。此时不可以进行入栈操作,但是可以进行进栈操作。

示例代码如下:

int STIsFull(StackType *s)
{
int t;
t=(s->top==MAXLEN);
return t;
}

输入参数s为一个指向操作的栈的指针。根据栈顶指针top判断是否和MAXLEN相等,判断栈是否已满。

清空栈

清空栈就是栈中所有的数据被清除。 示例代码如下:

void STClear(StackType *s)
{
s->top=0;
}

将栈顶指针top设置为0,表示执行清空栈操作。(这里只是逻辑上将栈中数据清空,实际上只是将top设置为0,以后再添加数据会覆盖原来的数据)

释放空间

释放空间是释放栈结构所占用的内存单元,使用delete释放用new运算符申请的内存空间。

示例代码如下:

void STFree(StackType *s)
{
delete s;
}

在程序中直接调用delete运算符释放已分配的内存空间。一般在不需要使用栈结构时调用该函数,特别是在程序结束的时候。

入栈

入栈(Push)是栈结构的基本操作,主要操作是将数据元素保存到栈结构。入栈操作的具体步骤如下:

(1)首先判断栈顶top,如果top大于等于MAXLEN,则表示溢出,进行出错处理。否则执行以下操作。

(2)设置top=top+1(栈顶指针加1,指向入栈地址)

(3)将入栈呀U尿素保存到top指向的位置。

示例代码如下:

int PushST(StackType *s,DATA data)
{
if((s->top+1)>MAXLEN)
{
cout<<"栈溢出"<<endl;
return 0;
}
s->data[++s->top]=data; //将元素压入栈
return 1;
}

输入参数s为一个指向操作的栈的指针,输入参数data是需要入栈的数据元素。程序首先判断栈是否溢出,如果溢出就给出警告,不进行入栈操作,否则修改栈顶指针,即top先加1,然后将data放到top现在指向的数据单元。

出栈

出栈(Pop)是占据诶狗的基本操作,主要操作与入栈相反,它是从栈顶弹出一个数据元素,出栈操作的具体步骤如下:

(1)首先判断栈顶top,如果top等于0,则表示为恐慌在哪,进行出错处理。否则执行下面的操作。

(2)将栈顶指针top所指向的位置的元素返回(实际是返回的指针)

(3)将top的减1,指向栈的下一个元素,原来栈顶的元素被弹出。

DATA * PopST(StackType *s)
{
if(s->top==0)
{
cout<<"栈为空,不能再输出!"<<endl;
exit(0);
}
return &(s->data[s->top--]);
}

当栈中有数据时,该函数返回值是一个指向DATA类型数据的指针。

读取点结构

读取点结构也就是读取栈结构中结点的数据。由于栈结构只能在一端进行操作,因此这里的读操作其实就是读站点的数据。

需要注意的是,读节点数据的操作和出栈操作不同。读结点操作仅仅是显示栈顶结点数据的内容,而出栈操作则将栈顶数据弹出。

示例代码如下:

DATA *PeekST(StackType *s)
{
if(s->top==0)
{
cout<<"栈已空"<<endl;
exit(0);
}
return &(s->data[s->top]);
}

对比出栈的示例代码,不难发现读取点结构同样返回了栈顶结点的地址,但是却没有使top减1.

完整示例

下面是栈的基本操作的完整示例:

程序代码:

#include<iostream>
#include<string>
using namespace std;
#define MAXLEN 50
struct DATA
{
string name;
int age;
};
struct StackType
{
DATA data[MAXLEN+1];
int top;
};
/******************初始化栈结构****************/
StackType *STInit()
{
StackType *p;
if(p=new StackType) //申请栈空间
{
p->top=0; //设置栈顶为0
return p; //返回栈顶指针
}
return NULL;
}
/****************判断空栈**********************/
int STIsEmpty(StackType *s)
{
int t;
t=(s->top==0); //通过栈顶的值进行判断
return t;
}
/**********************判断满栈****************/
int STIsFull(StackType *s)
{
int t;
t=(s->top==MAXLEN);
return t;
}
/**********************清空栈**********************/
void STClear(StackType *s)
{
s->top=0;
}
/********************释放空间********************/
void STFree(StackType *s)
{
delete s;
}
/**********************入栈***********************/
int PushST(StackType *s,DATA data)
{
if((s->top+1)>MAXLEN)
{
cout<<"栈溢出"<<endl;
return 0;
}
s->data[++s->top]=data; //将元素压入栈
return 1;
}
/************************出栈***********************/
DATA * PopST(StackType *s)
{
if(s->top==0)
{
cout<<"栈为空,不能再输出!"<<endl;
exit(0);
}
return &(s->data[s->top--]);
}
/**********************读取点结构*******************/
DATA *PeekST(StackType *s)
{
if(s->top==0)
{
cout<<"栈已空"<<endl;
exit(0);
}
return &(s->data[s->top]);
}
/*****************进入主函数**********************/
int main()
{
StackType *stack;
DATA data,*p_data;
stack=STInit();
cout<<"===============入栈操作:============="<<endl;
cout<<"输入姓名 ,年龄进行入栈操作:"<<endl;
//执行入栈操作
while(1)
{
cin>>data.name>>data.age;
if(data.name=="0")
{
break; //当姓名和年龄都是0的时候退出输入
}else
{
PushST(stack,data);
} }
p_data=PopST(stack);
cout<<"弹出栈顶元素"<<endl;
cout<<"name:"<<p_data->name<<",age:"<<p_data->age<<endl;
p_data=PeekST(stack);
cout<<"输出栈顶元素"<<endl;
cout<<"name:"<<p_data->name<<",age:"<<p_data->age<<endl;
cout<<"================将所有的的数据出栈:============="<<endl;
while(1)
{
p_data=PopST(stack);
cout<<"name:"<<p_data->name<<",age:"<<p_data->age<<endl;
}
STFree(stack);
return 0;
}

程序运行界面:

C++中栈结构建立和操作的更多相关文章

  1. C++中队列的建立和操作

    什么是队列结构 队列结构是从数据运算来分类的,也就是说队列结构具有特殊的运算规则.而从数据的逻辑结构来看,队列结构其实就是一种线性结构.如果从数据的存储结构来进一步划分,队列结构可以分成两类. 顺序队 ...

  2. Java中栈结构的自我实现

    package com.pinjia.shop.common.collection; /** * Created by wangwei on 2017/1/3. */ public class MyL ...

  3. mysql中树形结构表的操作

    一种是:邻接表模型(局限性:对于层次结构中的每个级别,您需要一个自联接,并且随着连接的复杂性增加,每个级别的性能自然会降低.在纯SQL中使用邻接列表模型充其量是困难的.在能够看到类别的完整路径之前,我 ...

  4. (js描述的)数据结构[栈结构](2)

    (js描述的)数据结构[栈结构](2) 一.什么是栈结构 1.一种受限制的线性结构,这种结构可以基于数组来实现. 2.可以抽象成一个容器,上面的是栈顶,底下的是栈底.所以仅允许对栈顶进行操作, 二.栈 ...

  5. 一文教你搞懂 Go 中栈操作

    转载请声明出处哦~,本篇文章发布于luozhiyun的博客:https://www.luozhiyun.com/archives/513 本文使用的go的源码15.7 知识点 LInux 进程在内存布 ...

  6. 栈的存储结构和常见操作(c 语言实现)

    俗话说得好,线性表(尤其是链表)是一切数据结构和算法的基础,很多复杂甚至是高级的数据结构和算法,细节处,除去数学和计算机程序基础的知识,大量的都在应用线性表. 一.栈 其实本质还是线性表:限定仅在表尾 ...

  7. javascript中的栈结构

    1.栈的定义 栈是一种和列表类似的数据结构,可以用它来解决很多的编程问题,栈是一种高效的数据结构,因为数据只能在栈的顶端添加或者删除,所以这样的操作很快而且容易实现. 栈是一种特殊的列表,站内的元素只 ...

  8. 第69节:Java中数据库的多表操作

    第69节:Java中数据库的多表操作 前言 学习数据库的多表操作,去电商行业做项目吧!!! 达叔,理工男,简书作者&全栈工程师,感性理性兼备的写作者,个人独立开发者,我相信你也可以!阅读他的文 ...

  9. java对象在内存中的结构(HotSpot虚拟机)

    一.对象的内存布局 HotSpot虚拟机中,对象在内存中存储的布局可以分为三块区域:对象头(Header).实例数据(Instance Data)和对齐填充(Padding). 从上面的这张图里面可以 ...

随机推荐

  1. ios多种语言的本地化思路

    多语言在应用程序中一般有两种做法: 一.程序中提供给用户自己选择的机会: 二.根据当前用户当前移动设备的语言自动将我们的app切换对应语言. 第一种做法比较简单完全靠自己的发挥了,这里主要讲第二种做法 ...

  2. [原创]java WEB学习笔记29:Cookie Demo 之自动登录

    本博客为原创:综合 尚硅谷(http://www.atguigu.com)的系统教程(深表感谢)和 网络上的现有资源(博客,文档,图书等),资源的出处我会标明 本博客的目的:①总结自己的学习过程,相当 ...

  3. SS中的三种样式来源:创作人员、读者和用户代理

    CSS中的样式一共有三种来源:创作人员.读者和用户代理,来源的不同会影响到样式的层叠方式,很多第一次学习CSS的朋友,对这三种来源可能会存在一些困惑,下面我写一下自己的理解,若有错误的地方还请指正. ...

  4. 汇编语言入门(在debug中编辑和调试程序)

    2013-06-02 17:09 4252人阅读 评论(2) 收藏 举报  分类: 汇编语言(1)  版权声明:本文为博主原创文章,未经博主允许不得转载. 我们在Windows中进入的Dos方式,实际 ...

  5. Future模式实例

    Future模式 /** * qccr.com Inc. * Copyright (c) 2014-2016 All Rights Reserved. */ package com.youqianhu ...

  6. 仿联想商城laravel实战---2、后端页面搭建(验证码如何在页面中使用)

    仿联想商城laravel实战---2.后端页面搭建(验证码如何在页面中使用) 一.总结 一句话总结: 放在img里面,img的src就是生产验证码的控制器路径: img src="/admi ...

  7. php数据结构课程---4、栈(是什么)

    php数据结构课程---4.栈(是什么) 一.总结 一句话总结: 栈(stack),它是一种运算受限的线性表.其限制是仅允许在表的一端进行插入和删除运算. 1.栈的链表实现? 定义node,设置属性d ...

  8. mysql的SQL_CALC_FOUND_ROWS 使用 类似count(*) 使用性能更高

    mysql的SQL_CALC_FOUND_ROWS 使用 类似count(*) 使用性能更高 在很多分页的程序中都这样写: SELECT COUNT(*) from `table` WHERE ... ...

  9. 大数据日志分析产品——SaaS Cloud, e.g. Papertrail, Loggly, Sumo Logic;Open Source Frameworks, e.g. ELK stack, Graylog;Enterprise Products, e.g. TIBCO LogLogic, IBM QRadar, Splunk

    Learn how you can maximize big data in the cloud with Apache Hadoop. Download this eBook now. Brough ...

  10. BEC listen and translation exercise 39

    What about jigsaw puzzle design for visually handicapped?给视觉障碍人士设计拼图怎么样? Length is 50cm, and then th ...