什么是栈结构

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

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

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

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

顺序栈结构:

即使用一组地址连续的内存单元依次保存栈中的数据。在程序中,可以定义一个指定大小的结构数组来作为栈,序号为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. HDU - 5695 Gym Class 【拓扑排序】

    题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=5695 思路 给定一些关系 进行拓扑排序 但是有一个要求 对于哪些没有确切的位置的点 要按照ID大小 I ...

  2. 回忆基础:制作plist文件

    -(void)creatPlistFileWithArr:(NSArray *)array{ //将字典保存到document文件->获取appdocument路径 NSString *docP ...

  3. FreeMarker使用后台枚举

    //页面使用枚举全路径访问 model.addAttribute("enums", BeansWrapper.getDefaultInstance().getEnumModels( ...

  4. 【leetcode刷题笔记】3Sum

    Given an array S of n integers, are there elements a, b, c in S such that a + b + c = 0? Find all un ...

  5. debian下配置dynamic printk以及重新编译内核

    在以前的一篇博文<编译debian内核>已经提过了重新编译内核的方法,但是整个过程花费时间较长,并且生成deb包. 这里我采用稍微简单一些的方法,因为我并没有对内核或者驱动代码做任何修改, ...

  6. FOJ 2232 匈牙利算法找二分图最大匹配

    题目链接 简单理解匈牙利算法 简单理解二分图 尽量让每一个随从击败一个对手且随从全部存活,关键是为每一个随从找对手(递归过程),"腾". #include<iostream& ...

  7. 处理 javax.el.ELException: Failed to parse the expression 报错

    在JSP的表达式语言中,使用了  <h3>是否新Session:${pageContext.session.new}</h3>  输出Session是否是新的,此时遇到了  j ...

  8. Java 环境变量设置 -- JAVA_HOME CLASSPATH

    1.打开我的电脑--属性--高级--环境变量 2.新建系统变量JAVA_HOME 和CLASSPATH 变量名:JAVA_HOME 变量值:C:\Program Files\Java\jdk1.7.0 ...

  9. Spring4面向切面AOP

    AOP(Aspect Oriented Programming)面向切面编程,通过预编译方式和运行期动态代理实现程序功能的横向多模块统一控制的一种技术.AOP是OOP的补充,是spring框架中的一个 ...

  10. Java 网络通信(TCP/UDP)

    1.InetAdress类 与  Socket类  >InetAdress  >Socket 2.TCP/IP协议簇  客户端: 创建 Socket:根据指定服务端的 IP 地址或端口号构 ...