学《数据结构》越学越聪明--第三章》》》栈和队列(一) 栈

栈的概述

栈是一种只能从一端插入的线性表

只能在同一个端进行插入和删除

在这里插入图片描述

栈的几个概念
  • 允许插入和删除的一端称为栈顶

  • 另一端称为栈底

  • 栈中没有元素时称为空栈

  • 栈的插入操作通常称为进栈或入栈

  • 栈的删除操作通常称为出栈或退栈

在这里插入图片描述

栈的特点:

栈的主要特点是后进先出即后进栈的元素先出栈。栈也被称为后进先出表

在这里插入图片描述

设一个栈的输入序列为a,b,c,d,则借助一个栈所得到的输出序列不可能是_D__

A,c,d,b,a        B,d,c,b,a        C,a,c,d,b        D,d,a,b,c


抽象数据类型=逻辑结构+基本运算(运算描述)

栈的几种基本运算如下:
  1. InitStack(&s)初始化栈。构造一个空栈s

  2. DestroyStack(&s)销毁栈。释放栈s所占的存储空间

  3. StackEmpty(s)判断栈是否为空:若栈s为空,则返回真,否则返回假

  4. Push(&s,e)进栈,将元素e插入栈s中作为栈顶元素,栈顶指针加1

  5. Pop(&s,&e)出栈,从栈s中退出栈顶元素,并且将其赋值给e

  6. GetTop(s,&e)取栈顶元素。返回当前栈顶元素,将其赋值给e

栈中元素逻辑关系与线性表中的相同,栈可以采用与线性表相同的存储结构。

在这里插入图片描述

栈的顺序存储结构

顺序栈

假设栈中的存储元素个数最大不超过正整数MaxSize个,所有元素类型都具有相同一数据类型ElemType,则可以用以下方式来定义顺序栈类型SqStack
typedef struct 
{
ElemType daat[MaxSize];
int top; 	  //栈顶指针
}SqStack;

在这里插入图片描述

小结
  • 约定top总是指向栈顶元素,初始值为-1
  • 当top=MaxSize-1时不能再进栈-栈满
  • 进栈时top增1,出栈时top减1

顺序栈的四要素

  1. 栈空条件栈顶指针top=-1

  2. 栈满条件栈顶指针top=MaxSize-1

  3. 元素e进栈操作top++;将元素e放入top处

  4. 元素e出栈操作从top处取出元素e,top--

在顺序栈中实现栈基本运算的算法

InitStack(&s)初始化栈

建立一个新的栈s,实际上是将栈顶指针指向-1即可
//初始化栈
void InitStack(SqStack* &s) {
	//s为栈指针,top为s所指的栈的指针
	s = (SqStack*)malloc(sizeof(SqStack));   //分配栈空间
	s->top = -1;  //初始化栈顶指针
}
注意:s为栈指针,top为s所指的栈的栈顶指针

DestroyStack(&s)销毁栈

释放栈s的存储空间
//销毁栈
void DestroyStack(SqStack *&s) {
	free(s)
}

StackEmpty(s)判断是否为空

栈s为空的条件是s->top==-1,即单链表的中没有数据元素
//判断栈是否为空
bool StackEmpty(SqStack* s) {
	return s->top == -1;
}

Push(&s,e)进栈

在栈不满的情况下,先将top指针+1,然后将元素e插入在top处
//进栈
bool PushStack(SqStack* &s, Elemtype e) {
	if (s->top == MaxSize - 1)  //栈满
		return false;
	s->top++;  //栈顶指针加1
	s->data[s->top] = e; //将元素e赋值给栈顶指针处
	return true;
}

Pop(&s,&e)出栈

在栈不为空的情况下,将栈顶元素赋值给e,然后再将栈顶指针-1
//出栈
bool PopStack(SqStack*&s,Elemtype &e) {
	if (s->top == -1)return false;   //栈空
	e=s->data[s->top];   //将栈顶指针元素值赋值给元素e
	s->top--;
	return true;
}

GetTop(s,&e)获取栈顶元素

在栈不为空的情况下,将栈顶元素赋值给e
//取栈顶元素
bool GetTop(SqStack* s, Elemtype* e) {
	if (s->top == -1)return false;
	e = s->data[s->top];
	return true;
}

顺序栈练习

设计一个算法利用顺序zhan判断一个字符串是否是对称串。所谓对称串是指从左往右读和从右往左读的序列是相同的。
算法设计思路
字符串str的所有元素依次进栈,产生出栈序列正好与str的顺序相同=》str是对称串
bool symmtry(Elemtype str[]) {
	int i = 0;SqStack* s;Elemtype e;
	InitStack(s);   //初始化栈s
	for ( i = 0; str[i]!='/0'; i++)   //将所有元素进栈
	{
		Push(s, str[i]);  //元素进栈
	}
	for ( i = 0; str[i] != '/0'; i++)    
	{
		Pop(s, e);   //退栈元素e
		if (str[i] != e) {   //若当前元素和元素e不同则不是对称串
			DestroyStack(s);   //销毁栈
			return false;   //返回假
		}
	}
	DestroyStack(s);
	return true;
}

栈的链式存储结构

栈的链式存储结构及其基本运算的实现

采用链式存储的栈称为链栈,这里采用带头结点的单链表实现

在这里插入图片描述

链栈的四要素

  1. 栈空条件s->next==NULL;

  2. 栈满条件不考虑

  3. 元素e进栈操作将包含元素e的结点插入到头结点之后

  4. 元素e出栈操作去除头结点之后的元素并删除

链栈中数据结点的类型LiStack定义如下:
typedef struct LinkNode
{
Elemtype data;  //数据域
struct LinkNode * next;  //指针域
}  LiStack; 

在链栈中。栈的基本运算算法如下:

InitStack(&s)初始化栈

建立一个空栈,并且创建头结点,将头结点置为NULL
//初始化栈
void InitStack(LiStack* &s) {
	//s为栈指针,top为s所指的栈的指针
	s = (LiStack*)malloc(sizeof(LiStack));   //分配栈空间
	s->next = NULL;  //初始化栈顶指针
}

DestroyStack(&s)销毁栈

释放栈s的全部存储空间
//销毁栈
void DestroyStack(LiStack *&s) {
	LiStack *p=s,*q=s-next;
	while(q!=NULL)
	{
	free(p);
	p=q;
	q=p->next;
	}
	free(p);  //此时p指向尾结点,释放其空间
}

StackEmpty(s)判断是否为空

栈s为空的条件是s->next==NULL,即单链表的中没有数据结点
//判断栈是否为空
bool StackEmpty(LiStack* s) {
	return s->next==NULL;
}

Push(&s,e)进栈

将数据结点插入到头结点之后
//进栈
void PushStack(LiStack* &s, Elemtype e) {
	LiStack *p;
	p=(LiStack *)malloc(sizeof(LiStack));
	p->data=e;  //新建元素e对应的结点*p
	p->next=s->nxet;  //插入p结点作为s的开始结点
	s->next=p;
}

Pop(&s,&e)出栈

在栈不为空的情况下,将头结点后继数据结点的数据域赋给e,然后将其删除
//出栈
bool PopStack(LiStack*&s,Elemtype &e) {
	LiStack *p;
	if(s->next==NULL)return false;
	p=s->next;
	e=p->data;
	s->next=p->next;
	free(p);
	retuen true;
}

GetTop(s,&e)获取栈顶元素

在栈不为空的情况下,将头结点后继数据元素结点的数据域赋值给e
//取栈顶元素
bool GetTop(LiStack* s, Elemtype* e) {
	if(s->next==NULL)return false;
	e=s-next->data;
	return true;
}

链栈和顺序栈两种存储结构有什么不同?

编写一个算法判断输入的表达式中括号是否配对(假设只含有左、右圆括号)

算法设计思路

一个表达式中左右括号是按最近位置配对的。所以利用一个栈来进行求解。这里采用链栈 遇到左括号进栈,遇到右括号出栈,最后查看栈内是否为空栈,如果是空栈那么成功配对,否则失败
bool Match(char exp[],int n)
{
LiStack * s;
int i=0;
char e;
bool match=true;
InitStack(s);  //初始化链栈
while(i<n&&match)   //扫描exp中所有字符
{
	if(exp[i]=='(')  //遇到任何左括号都进栈
	{
	Push(s,exp[i])
	}else if(exp[i]==')')  //当前字符为右括号
	{
		if(GetTop(s,e)==true) 
		{
			if(e!='('){match=false;}  //栈顶元素不为左括号时不匹配
			else{Pop(s,e)}  //出栈
		}
		else
		{
		match=false;  //无法取出栈顶元素时不匹配
		}
	}
}
if(!StackEmpty(s))  //运算完栈不空表示不匹配
return false;
DestroyStack(s);
return match;
}
  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

雷军的小宝贝

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值