当前位置:网站首页>学习笔记:第三章 栈与队列
学习笔记:第三章 栈与队列
2022-08-08 20:21:00 【程序猿小张的日常笔记】
第三章 栈与队列
第一部分 栈
1. 栈的定义
栈(stack)是限定仅在表尾进行插入和删除操作的线性表。
我们把允许插入和删除的一端称为栈顶(top),另一端称为栈底(bottom),不含任何数据元素的栈称为空栈。
栈又称为后进先出的线性表,简称LIFO结构。
栈的插入操作,叫作进栈,也称压栈。栈的删除操作,叫作出栈,有的也叫做弹栈。
2. 栈的抽象数据类型
ADT 栈(stack)
Data
同线性表。元素具有相同的类型,相邻元素具有前驱和后继关系。
Operation
InitStack(&S): 初始化操作,建立一个空栈s。
DestroyStack(&S): 若栈存在,则销毁它。
ClearStack(&S): 将栈清空。
StatckEmpty(S): 若栈存在且非空,返回true,否则返回false。
GetTop(S,&e): 若栈存在且非空,用e返回S的栈顶元素。
Push(&S,e): 若栈S存在,插入新元素e到栈S中并成为其栈顶对象。
Pop(&S,&e): 删除栈S中的栈顶元素,并用e返回其值。
StackLength(S): 返回栈S的元素个数。
StackTraverse(S,visit()): 栈S已存在且非空。从栈底到栈顶依次对S的每个数据元素调用visit()。
endADT
3. 栈的顺序存储结构及实现
顺序栈,即栈的顺序存储结构是利用一组地址连续的存储单元依次存放自栈底到栈顶的数据元素,同时附设指针top指示栈顶元素再顺序栈中的位置。(top=0表示空栈)。
首先,先为栈分配一个基本容量,然后在应用的过程中,当栈的空间不够使用时再逐段扩大。为此,设定两个常量:STACK_INIT_SIZE (存储空间初始分配量) 和 STACKINCREMENT (存储空间分配增量)。
(一)栈的定义方式:
typedef struct{
SElemtype *base; //栈底指针
SElemtype *top; //栈顶指针
int stacksize; //当前可使用的最大容量
}SqStack;
(1)栈的初始化:
Status InitStack(SqStack &S){
S.base=(SElemtype *)malloc(STACK_INIT_SIZE*sizeof(SElemtype));
if(!S.base) //如果base的值为空,则表明结构体不存在
return(OVERFLOW);
S.top=S.base; //(top=base 可作为栈为空的标记)
S.stacksize=STACK_INIT_SIZE; //按照初始分配量进行第一次存储分配
return OK;
}
(2)栈的销毁:
Status DestoryStack(SqStack &S)
{
free(S.base);
S.base = NULL;
S.top = NULL;
S.stacksize = 0;
return OK;
}
(3)栈的清空:
Status ClearStack(SqStack &S)
{
S.top = S.base;
return OK;
}
(4)判断栈是否为空:
Status StackEmpty(SqStack S)
{
if(S.top == S.base)
return TRUE;
else
return FALSE;
}
(5)返回栈顶元素:
Status GetTop(SqStack S,SElemType &e)
{
if(S.top == S.base)
return ERROR;
e = *(S.top -1);
return OK;
}
(6)压栈:
Status Push(SqStack &S, SElemType e)
{
if(S.top - S.base >= S.stacksize) //栈满,追加存储空间
{
S.base = (SElemType *)realloc(S.base,(S.stacksize + STACKINCREMENT)*sizeof(SElemType));
if(!S.base)
exit(OVERFLOW);
S.top = S.base + S.stacksize;
S.stacksize += STACKINCREMENT;
}
*S.top++ = e;
return OK;
}
(6)出栈:
Status Pop(SqStack &S, SElemType &e)
{
if(S.top == S.base) return ERROR;
e = * --S.top;
return OK;
}
(7)栈的元素个数:
int StackLength(SqStack S)
{
return S.top - S.base;
}
(8)栈元素从栈底依次输出:
Status StackTraverse(SqStack S, Status(* visit)(SElemType))
{
while(S.top > S.base)
visit(*S.base++);
printf("\n");
return OK;
}
Status visit(SElemType e)
{
printf("%d ", e);
return OK;
}
(二)栈的另一种方式定义方式:
typedef struct
{
SElemType data[MAXSIZE];
int top; // 用于栈顶指针
}SqStack;
(1)栈的初始化:
Status InitStack(SqStack &S)
{
/* S.data=(SElemType *)malloc(MAXSIZE*sizeof(SElemType)); */
S.top=-1;
return OK;
}
(2)栈的清空:
Status ClearStack(SqStack &S)
{
S.top=-1;
return OK;
}
(3)判断栈是否为空:
Status StackEmpty(SqStack S)
{
if (S.top==-1)
return TRUE;
else
return FALSE;
}
(4)返回栈顶元素:
Status GetTop(SqStack S,SElemType &e)
{
if (S.top==-1)
return ERROR;
else
e=S.data[S.top];
return OK;
}
(5)压栈:
Status Push(SqStack &S,SElemType e)
{
if(S.top == MAXSIZE -1)
{
return ERROR;
}
S.top++; //栈顶指针增加一
S.data[S.top]=e; //将新插入元素赋值给栈顶空间
return OK;
}
(6)出栈:
Status Pop(SqStack &S,SElemType &e)
{
if(S.top==-1)
return ERROR;
e=S.data[S.top];
S.top--;
return OK;
}
(7)栈的元素个数:
int StackLength(SqStack S)
{
return S.top+1;
}
(8)栈元素从栈底依次输出:
Status visit(SElemType c)
{
printf("%d ",c);
return OK;
}
Status StackTraverse(SqStack S)
{
int i;
i=0;
while(i<=S.top)
{
visit(S.data[i++]);
}
printf("\n");
return OK;
}
4. 两栈共享空间
将一个栈的栈底为数组的始端,即下标为0处。另一个栈为数组的末端,即下标为数组长度n-1处。
两个栈如果增加元素,就是两端点向中间延伸。
typedef struct
{
SElemType data[MAXSIZE];
int top1; //栈1栈顶指针
int top2; //栈2栈顶指针
}SqDoubleStack;
(1) 栈的初始化:
Status InitStack(SqDoubleStack &S)
{
S.top1=-1;
S.top2=MAXSIZE;
return OK;
}
(2) 栈的清空:
Status ClearStack(SqDoubleStack &S)
{
S.top1=-1;
S.top2=MAXSIZE;
return OK;
}
(3) 判断栈是否为空:
Status StackEmpty(SqDoubleStack S)
{
if (S.top1==-1 && S.top2==MAXSIZE)
return TRUE;
else
return FALSE;
}
(4) 压栈:
//插入元素e为新的栈顶元素
Status Push(SqDoubleStack &S,SElemType e,int stackNumber)
{
if (S.top1+1==S.top2) // 栈满
return ERROR;
if (stackNumber==1) //栈1有元素进栈
S.data[++S.top1]=e;
else if (stackNumber==2) //栈2有元素进栈
S.data[--S.top2]=e;
return OK;
}
(5) 出栈:
Status Pop(SqDoubleStack &S,SElemType &e,int stackNumber)
{
if (stackNumber==1)
{
if (S.top1==-1)
return ERROR;
e=S.data[S.top1--];
}
else if (stackNumber==2)
{
if (S.top2==MAXSIZE)
return ERROR;
e=S.data[S.top2++];
}
return OK;
}
(6) 栈的元素个数:
// 返回S的元素个数,即栈的长度
int StackLength(SqDoubleStack S)
{
return (S.top1+1)+(MAXSIZE-S.top2);
}
(7) 栈元素从栈底依次输出:
Status visit(SElemType c)
{
printf("%d ",c);
return OK;
}
Status StackTraverse(SqDoubleStack S)
{
int i;
i=0;
while(i<=S.top1)
{
visit(S.data[i++]);
}
i=S.top2;
while(i<MAXSIZE)
{
visit(S.data[i++]);
}
printf("\n");
return OK;
}
5. 栈的链式存储结构及实现
typedef struct StackNode
{
SElemType data;
struct StackNode *next;
}StackNode,*LinkStackPtr;
typedef struct
{
LinkStackPtr top;
int count;
}LinkStack;
(1) 栈的初始化:
Status InitStack(LinkStack &S)
{
S.top = (LinkStackPtr)malloc(sizeof(StackNode));
if(!S.top)
return ERROR;
S.top=NULL;
S.count=0;
return OK;
}
(2) 栈的清空:
//把S置为空栈
Status ClearStack(LinkStack &S)
{
LinkStackPtr p,q;
p=S.top;
while(p)
{
q=p;
p=p->next;
free(q);
}
S.count=0;
return OK;
}
(3) 判断栈是否为空:
//若栈S为空栈,则返回TRUE,否则返回FALSE
Status StackEmpty(LinkStack S)
{
if (S.count==0)
return TRUE;
else
return FALSE;
}
(4) 返回栈顶元素:
Status GetTop(LinkStack S,SElemType &e)
{
if (S.top==NULL)
return ERROR;
else
e=S.top->data;
return OK;
}
(5) 压栈:
Status Push(LinkStack &S,SElemType e)
{
LinkStackPtr s=(LinkStackPtr)malloc(sizeof(StackNode));
s->data=e;
s->next=S.top; // 把当前的栈顶元素赋值给新结点的直接后继。
S.top=s; // 将新的结点s赋值给栈顶指针
S.count++;
return OK;
}
(6) 出栈:
Status Pop(LinkStack &S,SElemType &e)
{
LinkStackPtr p;
if(StackEmpty(S))
return ERROR;
e=S.top->data;
p=S.top; //将栈顶结点赋值给p。
S.top=S.top->next; //使得栈顶指针下移一位,指向后一结点。
free(p);
S.count--;
return OK;
}
(7) 栈的元素个数:
int StackLength(LinkStack S)
{
return S.count;
}
(8) 栈元素依次输出:
Status visit(SElemType c)
{
printf("%d ",c);
return OK;
}
Status StackTraverse(LinkStack S)
{
LinkStackPtr p;
p=S.top;
while(p)
{
visit(p->data);
p=p->next;
}
printf("\n");
return OK;
}
但行好事,莫问前程。
不忘初心,方得始终。
做好自己,温暖且积极!!!
边栏推荐
猜你喜欢
iMeta | 深圳先进院戴磊组开发可同时提取共存菌株的组成和基因成分谱的菌株分析工具...
西湖大学鞠峰组招聘【塑料降解 / 污水工程 / 微生物学】方向博士后和科研助理...
IJCAI 2022 | 图神经网络可以检测到异常吗?
微信小程序第一集
2022-08-08 第六小组 瞒春 学习笔记
虚假信息处理最新有何进展?KDD2022《打击错误信息和应对媒体偏见》教程,161页ppt
莫让“学院派”限制我们的思维:在数组的中间位置删除数据一定比链表慢?
Maykel Studio OpenHarmony Device Development Training Notes - Chapter 6 Study Notes
梅科尔工作室OpenHarmony设备开发培训笔记-第六章学习笔记
一文教你普罗米修斯Prometheus的基础应用
随机推荐
Codeforces Round #722 (Div. 2)
iMeta | 深圳先进院戴磊组开发可同时提取共存菌株的组成和基因成分谱的菌株分析工具...
LeetCode_67_二进制求和
微信小程序第一集
What are the latest developments in the handling of false information?KDD2022 "Fighting Misinformation and Responding to Media Bias" tutorial, 161 pages ppt
RADIUS服务器的演变过程
给大龄准备转行网络工程师的朋友一些建议
wps表格怎么复制粘贴后与原来格式一样?
1088 N的阶乘
箭头函数this指向的解释
制作实例分割数据集
Wps文档云同步如何开启?Wps打开文档云同步的方法
CSP-J2021 题解
laravel run scheduler command on weekdays (except holidays)
有幸与美团大佬共同探讨单节点连接数超1.5W的问题
莫让“学院派”限制我们的思维:在数组的中间位置删除数据一定比链表慢?
What are the role of document management system for companies?
DCT变换
经验分享|低成本快节奏搭建企业知识管理系统的方法
投资基金定投安全吗