【数据结构】栈和队列详细分析(全)

article/2025/11/7 11:39:52

目录

  • 1.前言
  • 2.栈的定义与特点
    • 2.1顺序栈的定义
    • 2.2顺序栈的操作
    • 2.3链栈的定义
    • 2.4链栈的操作
  • 3.队列的定义与特点
    • 3.1循环队列
    • 3.2循环队列的操作
    • 3.3链队的定义
    • 3.4链队的操作
  • 4.总结

1.前言

栈和队列是两种重要的线性结构。从数据结构角度看,栈和队列也是线性表, 其特殊性在于栈和队列的基本操作是线性表操作的子集,它们是操作受限的线性表,因此,可称为限定性的数据结构。

2.栈的定义与特点

栈是限定仅在表尾进行插入或删除操作的线性表。 表尾称为栈顶,表头端称为栈底 。不含元素的空表称为空栈。栈的修改是按后进先出的原则进行的。

2.1顺序栈的定义

顺序栈是指利用顺序存储结构实现的栈,即利用一组地址连续的存储单元依次存放自栈底到栈顶的数据元素,同时附设指针 top指示栈顶元素在顺序栈中的位置。通常习惯的做法是:以top=0表示空栈

顺序栈的存储结构:

#define MAXSIZE 100 //顺序栈存储空间的初始分配址
typedef struct{
SElemType *base;//栈底指针
SElemType *top;//栈顶指针
int stacksize;//栈可用的最大容扯
}SqStack; 

base 为栈底指针,初始化完成后,栈底指针 base 始终指向栈底的位置,若 base 的值为NULL, 则表明栈结构不存在。top 为栈顶指针,其初值指向栈底。每当插入新的栈顶元素时,指针 top 增1; 删除栈顶元素时,指针 top减1。因此,栈空时,top 和 base 的值相等,都指向栈底;栈非空时,top 始终指向栈顶元素的上一个
在这里插入图片描述

2.2顺序栈的操作

1.初始化

Status InitStack(SqStack &S)//构造一个空栈s
S.base=new SElemType[MAXSIZE]; //为顺序栈动态分配一个最大容扯为 MAXSIZE 的数组空间
if (!S.base) exit (OVERFLOW); //存储分配失败
S.top=S.base;//top 初始为 base, 空栈
S.stacksize=MAXSIZE; //stacksize 置为栈的最大容量 MAXSIZE
return OK;
}

2.入栈

先判定条件是否为满
先入栈后指针加1:*S.top++=e;

Status Push (SqStack &S, SElemType e) 
{//插入元素e为新的栈顶元素
if(S.top-S.base==S.stacksize) return ERROR; //栈满
*S.top++=e; //元素 e 压入栈顶, 栈顶指针加 1
return OK;
}

3.出栈

先判定条件是否为空
先指针减1后出栈:e=*–S.top;

Status Pop(SqStack &S,SElemType &e)//删除s 的栈顶元素, 用 e 返回其值
if(S.top==S.base) return ERROR; 
e=*--S.top; 
return OK;
} 

4.取栈顶元素

SElemType GetTop{SqStack S) 
//返回 s 的栈顶元素, 不修改栈顶指针
if{S.top! =S.base) 
return *(S.top-1);
} 

2.3链栈的定义

链栈是指采用链式存储结构实现的栈
由于栈的主要操作是在栈顶插入和删除, 显然以链表的头部作为栈顶是最方便的, 而且没必要像单链表那样为了操作方便附加一个头结点。
链栈的存储结构:

typedef struct StackNode 
ElemType data;
struct StackNode *next; 
) StackNode,*LinkStack; 

链栈示意图

2.4链栈的操作

1.初始化
构造一个空栈,没有设置头结点,只需要栈顶指针置空即可

Status InitStack(LinkStack &S) 
{//构造一个空栈 s, 栈顶指针置空
S=NULL; 
return OK;
}

2.入栈

分配空间生成新结点,将新结点设置为e,插入栈顶,在修改指针

Status Push(LinkStack &S, SElemType e) 
{//在栈顶插入元素e
p=new StackNode; //生成新结点
p->data=e;//将新结点数据域置为e
p->next=S;//将新结点插人栈顶
S=p; //修改栈顶指针为p
return OK; 
}

3.出栈

Status Pop(LinkStack &S,SElemType &e) 
{//删除 s 的栈顶元素,用 e 返回其值
if(S==NULL) return ERROR; //栈空
e=S->data; //将栈顶元素赋给 e
p=S; //用 p 临时保存栈顶元素空间, 以备释放
S=S->next; //修改栈顶指针
delete p; //释放原栈顶元素的空间
return OK;
}

4.取栈顶元素

SElemType GetTop(LinkStack S) 
{//返回 s 的栈顶元素, 不修改栈顶指针
if(S! =NULL) //栈非空
return S->data; //返回栈顶元素的值,栈顶指针不变
}

3.队列的定义与特点

和栈相反,队列是一种先进先出的线性表。它只允许在表的一端进行插入,而在另一端删除元素,允许插入的一端称为队尾,允许删除的一端则称为队头。

3.1循环队列

和顺序栈相类似,在队列的顺序存储结构中,除了用一组地址连续的存储单元,依次存放从队列头到队列尾的元素之外,尚需附设两个整型变最 front 和 rear分别指示队列头元素及队列尾元素的位置(后面分别称为头指针和尾指针)

队列的顺序存储结构:

#define MAXQSIZE 100//队列可能达到的最大长度 
typedef struct 
{
QElemType *base; //存储空间的基地址
int front; //头指针
int rear; //尾指针
}SqQueue; 

初始化创建空队列时,令 front = rear = 0 , 每当插入新的队列尾元素时,尾指针 rear增1; 每当删除队列头元素时, 头指针 front增1。因此,在非空队列中,头指针始终指向队列头元素,而尾指针始终指向队列尾元素的下一个位置
在这里插入图片描述
图中的d中这种现象为假溢出,数组越界,但还是有空间而导致程序非法,无法在填充数据,为了解决这种假溢出,推出了循环队列
循环队列的结构图
提示:在循环队列中如何区分队列是否满还是空?
方法一:少用一个元素空间, 即队列空间大小为m时,有m-1个元素就认为是队满。这样判断队空的条件不变, 即当头、 尾指针的值相同时, 则认为队空;而当尾指针在循环意义上加1后是等于头指针, 则认为队满。 因此, 在循环队列中队空和队满的条件是:
队空的条件: Q.front = Q.rear
队满的条件: (Q rear+ 1)%MAXSIZE = Q.front

方法二:另设一个标志位以区别队列是 “空” 还是 “满

3.2循环队列的操作

1.初始化

Status InitQueue (SqQueue &Q) 
{//构造一个空队列Q
Q.base=new QElemType[MAXQSIZE]//为队列分配一个最大容扯为 MAXSIZE 的数组空间
if(!Q.base) exit(OVERFLOW);//存储分配失败
Q.front=Q.rear=0;//头指针和尾指针置为零, 队列为空
return OK;
}

2.求队列长度

int QueueLength(SqQueue Q) 
{//返回Q的元素个数, 即队列的长度
return(Q.rear-Q.front+MAXQSIZE)%MAXQSIZE;
}

3.入队

判断条件是否为满,插入元素,队尾指针加1

Status EnQueue (SqQueue &Q, QElemType e) 
{//插入元素 e 为 Q 的新的队尾元素
if ((Q. rear+1) %MAXQSIZE==Q. front)//尾指针在循环意义上加1后等于头指针,表明队满
return ERROR; 
Q.base[Q.rear]=e;//新元素插入队尾
Q.rear=(Q.rear+1)%MAXQSIZE;//队尾指针加1
return OK; 
}

4.出队

判断条件是否为空,保存队头元素,对头指针加1

Status DeQueue (SqQueue &Q, QElemType &e) 
{//删除Q的队头元素, 用 e 返回其值
if(Q.front==Q. rear) return ERROR; / /队空
e=Q.base[Q.front]; //保存队头元素
Q.front=(Q.front+1)%MAXQSIZE; //队头指针加1
return OK;
}

5.取对头元素

SElemType GetHead(SqQueue Q) 
{//返回Q的队头元素,不修改队头指针
if(Q. front! =Q. rear) //队列非空
return Q.base[Q.front]; //返回队头元素的值,队头指针不变
}

3.3链队的定义

链队是指采用链式存储结构实现的队列。 通常链队用单链表来表
示。 一个链队显然需要两个分别指示队头和队尾的指针(分别称为头指针和尾指针)才能唯一确定。 这里和线性表的单链表一样, 为了操作方便起见,给链队添加一个头结点, 并令头指针始终指向头结点

链队的存储结构:

typedef struct QNode
{
QElemType data; 
struct QNode *next; 
}QNode, *QueuePtr; typedef struct 
QueuePtr front; //队头指针
QueuePtr rear; //队尾指针
) LinkQueue; 

链队的操作即为单链表插入和删除操作的特殊情况,只是需进一步修改尾指针或头指针。

3.4链队的操作

1.初始化

Status InitQueue (LinkQueue &Q) 
{//构造一个空队列 Q
Q.front=Q.rear=new QNode;//生成新结点作为头结点,队头和队尾指针指向此结点
Q.front->next=NULL;//头结点的指针域置空
return OK;
}

2.入队

Status EnQueue (LinkQueue &Q, QElemType e) 
{//插入元素e为Q的新的队尾元素
p=new QNode; //为人队元素分配结点空间,用指针p指向
p->data=e; //将新结点数据域置为e
p->next=NULL; Q. rear->next=p; //将新结点插入到队尾
Q.rear=p; //修改队尾指针
return OK;
}

3.出队

Status DeQueue(LinkQueue &Q,QElemType &e) 
{//删除Q的队头元素, 用e返回其值 
if(Q.front==Q.rear) return ERROR; //若队列空, 则返回 ERROR
p=Q.front->next; //p指向队头元素
e=p->data; //e保存队头元素的值 
Q.front->next=p->next; //修改头指针
if(Q.rear= =p) Q.rear=Q.front; //最后一个元素被删, 队尾指针指向头结点 
delete p; //释放原队头元素的空间
return OK; 
}

4.取队头元素

SElemType GetHead{LinkQueue Q) 
{//返回Q的队头元素, 不修改队头指针
if(Q.front!=Q.rear) //队列非空
return Q.front->next->data; //返回队头元素的值,队头指针不变
}

4.总结

在这里插入图片描述


http://chatgpt.dhexx.cn/article/3f8E8xGL.shtml

相关文章

【Python数据结构系列】❤️《栈(顺序栈与链栈)》——❤️知识点讲解+代码实现

灵魂拷问:为什么要学数据结构? 数据结构,直白地理解,就是研究数据的存储方式。数据存储只有一个目的,即为了方便后期对数据的再利用。因此,数据在计算机存储空间的存放,决不是胡乱的&#xff0c…

数据结构——栈与队列

目录 一、栈 1.栈的定义 2.栈的分类与基本操作 1. 顺序栈 2.链栈 3.栈与递归的实现 1.递归的简单描述 2.递归过程及与栈的关联 3.递归过程示意图 二.队列 1.队列的定义 2.队列的分类与基本操作 1.顺序队列 2.链队列 3.循环队列 1.假溢出 2.循环队列 3.循环队列相…

栈与队列详解

目录 申明1. 栈的定义1.1 栈的定义1.2 进栈出栈变化形式 2. 栈的抽象数据类型3. 栈的顺序存储结构及实现3.1 栈的顺序存储结构3.2 栈的顺序存储结构——进栈操作3.3 栈的顺序存储结构——出栈操作 4. 两栈共享空间5. 栈的链式存储结构及实现5.1 栈的链式存储结构5.2 栈的链式存…

栈与队列(超详细)

目录 一、栈(Stack)1、什么是栈?2、栈的常见方法3、自己实现一个栈(底层用一个数组实现) 二、队列(Queue)1、什么是队列?2、队列的常见方法3、队列的实现(单链表实现&…

C语言---栈和队列

严格来说,栈和队列都属于线性表 "一对一" 栈:"先进后出" 队列: "先进先出" 栈 栈只能从一端存取,另一端是封闭的 在栈中,不论是存还是取,都必须遵循"先进后出"的原则 >栈是一种只能从表的一端存取数据,且遵循"先进后出…

数据结构与算法——栈和队列

😊数据结构与算法——栈和队列 🚀前言🚀栈(satck)🚢栈的定义🚢共享栈(节省空间)🚢栈的表示和实现(顺序栈)👻顺序栈的定义&…

数据结构:栈和队列(Stack Queue)【详解】

友情链接:数据结构专栏 目录 栈和队列【知识框架】 栈一、栈的基本概念1、栈的定义2、栈的常见基本操作 二、栈的顺序存储结构1、栈的顺序存储2、顺序栈的基本算法(1)初始化(2)判栈空(3)进栈&a…

web 移动端开发基础

web 移动端开发基础 文章目录 web 移动端开发基础了解视口相关内容meta 视口标签掌握二倍图用法物理像素 & 物理像素比多倍图二倍精灵图做法 了解移动端常见选择方案掌握移动端常见问题解决方案移动端常见的布局方式流式布局(百分比布局)flex 布局 -…

Web移动端

1.PC端和移动端的区别: PC端:屏幕大 用网页固定版心,要考虑浏览器兼容问题,(布局:浮动+定位+标准流) 移动端: 手机屏幕小,网页宽度多数为100%,是适配手机屏幕宽度 移动端则基本不需要考虑兼容性问题,放心大胆使用CS…

移动端网页开发基础

文章目录 前言一、浏览器1.pc端常见浏览器2.移动端常见浏览器 二、视口1.布局视口layout viewport2.视觉视口visual viewport3.理想视口ideal viewport 三、二倍图1.物理像素和物理像素比2.二倍图用法 四、移动端开发选择1.单独制作移动端页面2.响应式兼容pc移动端3.移动端常见…

20.【移动端Web开发之响应式布局】

文章目录 【移动端Web开发之响应式布局】前端小抄(20)一、响应式开发1.1 响应式开发原理1.2 响应式布局容器 二、Bootstrap前端开发框架2.1 Bootstrap简介2.2 Bootstrap使用2.3 布局容器 三、Bootstrap栅格系统3.1 栅格系统简介3.2 栅格选项参数3.3 列嵌套3.4 列偏移3.5 列排序…

H5移动web开发

目录 1、H5 的新特性有哪些?C3 的新特性有哪些? 2、如何使一个盒子水平垂直居中? 方法一:利用定位(常用方法,推荐) 方法二:利用 margin:auto 方法三:利用 display:table-cell 方法四…

手摸手带你学移动端WEB开发

HTML常用标签总结手摸手带你学CSSHTML5与CSS3知识点总结 好好学习,天天向上 本文已收录至我的Github仓库DayDayUP:github.com/RobodLee/DayDayUP,欢迎Star ⭐⭐⭐⭐⭐转载请注明出处!⭐⭐⭐⭐⭐ 链接:https://blog.c…

移动端网页开发(一)

一、项目代码初始化 1.打开index.html将<meta></meta>标签补充完整 <html><head><meta charset"utf-8"><meta name"viewport" content"widthdevice-width,initial-scale1.0&#xff0c;minimum-scale1.0,maximum-…

web移动开发

web移动开发 手机内置浏览器&#xff1a; Android&#xff1a;Andriod BrowserIOS&#xff1a;Mobile SafariBlackBerry&#xff1a;WebkitSymbian S60&#xff1a; Web Browser for S60 其浏览器的核心都是基于Webkit 智能手机Web浏览器的特点: 有限的屏幕尺寸触屏、缩放硬…

移动端页面开发

移动端页面开发需要掌握的…… 移动端开发指的是&#xff1a;需要适配移动设备的网页开发移动开发与pc端开发没有本质的区别&#xff0c;使用的也还是HTML/CSS/JS的技术 一、移动端与pc端开发的区别在于&#xff1a; 1.浏览器不同 手机浏览器是webkit的天下&#xff0c;就目…

从零开始学习移动端Web开发

背景 近年来&#xff0c;随着智能手机的普及&#xff0c;移动端开发受到了异常的关注。从传统的安卓、IOS原生手机系统应用开发&#xff0c;转向了移动端Web开发或者是混合开发&#xff0c;既然有需求&#xff0c;那就让我们一起来学习移动端Web开发吧。本文旨在让读者以最快的…

移动端网站开发

受限于流量太少&#xff0c;以前的手机网站无法做成像现在一样的效果&#xff0c;只能通过超链接的形式实现简单的网页 随着3G&#xff0c;4G&#xff0c;5G的商用&#xff0c;我们的流量越来越多&#xff0c;网速越来越快。越来越多的应用开始去开发网页版。 移动端仿真 未来…

移动端开发

2022.3.5 学习笔记 目录 四、移动端开发方案 五、 移动端技术解决方案 六、移动端常见布局 移动端开发之流式布局&#xff1a; 一、基础 二、制作京东移动端首页案例 四、移动端开发方案 ①单独制作移动端页面 &#xff08;主流&#xff09; 京东商城手机版 淘宝触屏版…

web前端开发之移动端基础

web前端开发之移动端基础 一、物理像素(px) 定义&#xff1a;虚拟像素&#xff0c;可以理解为“直觉”像素&#xff0c;CSS和JS使用的抽象单位&#xff0c;浏览器内的一切长度都是以CSS像素为单位的&#xff0c;CSS像素的单位是px。 1.2 像素到底是什么 像素&#xff08;px…