栈和队列基本操作

article/2025/9/17 5:52:09

栈和队列

  • 一、栈
    • 栈是什么
    • 栈的实现
    • 栈的基本操作
      • 栈类型的定义
      • 初始化栈
      • 检查栈是否为满
      • 入栈
      • 出栈
      • 获取栈顶元素
      • 检测栈是否为空
      • 测试函数
    • 完整代码
      • Stack.h
      • Stack.c
      • main.c
  • 二、队列
    • 队列是什么
    • 队列的实现
      • 队列类型的定义
      • 申请一个节点
      • 初始化队列
      • 队尾入队列
      • 队头出队列
      • 获取队列头部元素
      • 获取队列队尾元素
      • 获取队列中有效元素个数
      • 检测队列是否为空
      • 销毁队列
      • 测试函数
    • 完整代码
      • Queue.h
      • Queue.c
      • main.c
  • 三、环形队列
    • 假溢出问题

一、栈

栈是什么

  栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。栈中的数据元素遵守后进先出LIFO(Last In First Out)的原则。

压栈:栈的插入操作叫做进栈/压栈/入栈,入数据在栈顶。

出栈:栈的删除操作叫做出栈。出数据也在栈顶。
在这里插入图片描述

栈遵循先进后出原则
在这里插入图片描述

栈的实现

  栈的实现一般可以使用数组或者链表实现,相对而言数组的结构实现更优一些。因为数组在尾上插入数据的代价比较小。
在这里插入图片描述

栈的基本操作

栈类型的定义

typedef int STDataType;
typedef struct Stack
{STDataType* a;int top;   // 栈顶int capacity;  // 容量 int size;}Stack;

初始化栈

 void StackInit(Stack* ps)
{assert(ps);ps->a=(STDataType*)malloc(sizeof(STDataType)*5); if(NULL==ps->a){assert(0);return;}ps->capacity=5;ps->size=0;
}

检查栈是否为满

void CheckStack(Stack* ps)
{assert(ps);if(ps->capacity==ps->size){//1.申请空间int newcapacity=ps->capacity*2;STDataType *temp=(STDataType*)malloc(sizeof(STDataType)*newcapacity);if(temp==NULL){assert(0);return;}//2.拷贝元素memcpy(temp,ps->a,sizeof(STDataType)*ps->size);//3.释放旧空间free(ps->a);//4.使用新空间 ps->a=temp;ps->capacity=newcapacity;}
}

入栈

 void StackPush(Stack* ps, STDataType data)
{assert(ps);CheckStack(ps);ps->a[ps->size]=data;ps->size++;
}

出栈

 void StackPop(Stack* ps)
{assert(ps);if(!StackEmpty(ps)){ps->size--;}return;
}

获取栈顶元素

 STDataType StackTop(Stack* ps)
{assert(ps);return ps->a[ps->size-1];
}// 获取栈中有效元素个数 int StackSize(Stack* ps)
{assert(ps);return ps->size;
}

检测栈是否为空

 int StackEmpty(Stack* ps)
{assert(ps);return 0==ps->size;
}// 销毁栈 void StackDestroy(Stack* ps)
{assert(ps);if(ps->a){free(ps->a);ps->a=NULL;ps->capacity=0;ps->size=0;}
}

测试函数

void TestStack()
{Stack s;StackInit(&s);StackPush(&s,1);StackPush(&s,2);StackPush(&s,3);StackPush(&s,4);StackPush(&s,5);StackPush(&s,6);StackPush(&s,7);printf("%d\n",StackTop(&s));printf("%d\n",StackSize(&s));StackPop(&s);StackPop(&s);StackPop(&s);printf("%d\n",StackTop(&s));printf("%d\n",StackSize(&s));StackDestroy(&s);
}

完整代码

Stack.h

typedef int STDataType;
typedef struct Stack
{STDataType* a;int top;   // 栈顶int capacity;  // 容量 int size;}Stack;
// 初始化栈 void StackInit(Stack* ps); //检查栈是否为慢void CheckStack(Stack* ps);// 入栈 void StackPush(Stack* ps, STDataType data); // 出栈 void StackPop(Stack* ps); // 获取栈顶元素 STDataType StackTop(Stack* ps); // 获取栈中有效元素个数 int StackSize(Stack* ps); // 检测栈是否为空,如果为空返回非零结果,如果不为空返回0 int StackEmpty(Stack* ps); // 销毁栈 void StackDestroy(Stack* ps);void TestStack();

Stack.c

#include "Stack.h"#include<stdio.h>
#include<malloc.h>
#include<assert.h>
#include<string.h>// 初始化栈 void StackInit(Stack* ps)
{assert(ps);ps->a=(STDataType*)malloc(sizeof(STDataType)*5); if(NULL==ps->a){assert(0);return;}ps->capacity=5;ps->size=0;
}// 检查栈是否满void CheckStack(Stack* ps)
{assert(ps);if(ps->capacity==ps->size){//1.申请空间int newcapacity=ps->capacity*2;STDataType *temp=(STDataType*)malloc(sizeof(STDataType)*newcapacity);if(temp==NULL){assert(0);return;}//2.拷贝元素memcpy(temp,ps->a,sizeof(STDataType)*ps->size);//3.释放旧空间free(ps->a);//4.使用新空间 ps->a=temp;ps->capacity=newcapacity;}
}// 入栈 void StackPush(Stack* ps, STDataType data)
{assert(ps);CheckStack(ps);ps->a[ps->size]=data;ps->size++;
}// 出栈 void StackPop(Stack* ps)
{assert(ps);if(!StackEmpty(ps)){ps->size--;}return;
}// 获取栈顶元素 STDataType StackTop(Stack* ps)
{assert(ps);return ps->a[ps->size-1];
}// 获取栈中有效元素个数 int StackSize(Stack* ps)
{assert(ps);return ps->size;
}// 检测栈是否为空,如果为空返回非零结果,如果不为空返回0 int StackEmpty(Stack* ps)
{assert(ps);return 0==ps->size;
}// 销毁栈 void StackDestroy(Stack* ps)
{assert(ps);if(ps->a){free(ps->a);ps->a=NULL;ps->capacity=0;ps->size=0;}
}

void TestStack()
{Stack s;StackInit(&s);StackPush(&s,1);StackPush(&s,2);StackPush(&s,3);StackPush(&s,4);StackPush(&s,5);StackPush(&s,6);StackPush(&s,7);printf("%d\n",StackTop(&s));printf("%d\n",StackSize(&s));StackPop(&s);StackPop(&s);StackPop(&s);printf("%d\n",StackTop(&s));printf("%d\n",StackSize(&s));StackDestroy(&s);
}

main.c

#include "Stack.h"int main()
{TestStack();return 0;
}

二、队列

队列是什么

  队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出FIFO(First In First Out) 入队列:进行插入操作的一端称为队尾 出队列:进行删除操作的一端称为队头。
在这里插入图片描述

队列的实现

  队列也可以数组和链表的结构实现,使用链表的结构实现更优一些,因为如果使用数组的结构,出队列在数组头上出数据,效率会比较低。
在这里插入图片描述

队列类型的定义

 typedef int QDataType;typedef struct QNode { struct QNode* next; QDataType data; }QNode; // 队列的结构 typedef struct Queue { QNode* front; QNode* rear; int size;}Queue; 

申请一个节点

QNode* buyQNode(QDataType data)
{QNode *newnode=(QNode*)malloc(sizeof(QNode));if(NULL==newnode){assert(0);return NULL;}newnode->data=data;newnode->next=NULL;return newnode;
}

初始化队列

void QueueInit(Queue* q)
{assert(q);q->front=q->rear=NULL;q->size=0;}

队尾入队列

void QueuePush(Queue* q, QDataType data)
{assert(q);QNode *newnode=buyQNode(data);if(NULL==q->front){q->front=newnode; }else{q->rear->next=newnode; }q->rear=newnode;q->size++;
}

队头出队列

void QueuePop(Queue* q)
{assert(q);if(QueueEmpty(q)){return;}else{QNode *delndoe=q->front;q->front=delndoe->next;free(delndoe);if(NULL==q->front){q->rear=NULL;}}q->size--;
}

获取队列头部元素

 
QDataType QueueFront(Queue* q)
{assert(!QueueEmpty(q));return q->front->data;
}

获取队列队尾元素

QDataType QueueBack(Queue* q)
{assert(!QueueEmpty(q));return q->rear->data;
}

获取队列中有效元素个数

int QueueSize(Queue* q)
{assert(!QueueEmpty(q));return q->size;
}

检测队列是否为空

int QueueEmpty(Queue* q)
{assert(q);return NULL==q->front;
}

销毁队列

void QueueDestroy(Queue* q)
{assert(q);QNode *cur=q->front;while(cur){q->front=cur->next;free(cur);cur=q->front;}q->rear=NULL;q->size=0;
}

测试函数

void TestQueue()
{Queue q;QueueInit(&q);QueuePush(&q, 1);QueuePush(&q, 2);QueuePush(&q, 3);QueuePush(&q, 4);QueuePush(&q, 5);printf("%d\n", QueueFront(&q));printf("%d\n", QueueBack(&q));printf("%d\n", QueueSize(&q));QueuePop(&q);QueuePop(&q);QueuePop(&q);printf("%d\n", QueueFront(&q));printf("%d\n", QueueBack(&q));printf("%d\n", QueueSize(&q));QueuePop(&q);QueuePop(&q);QueuePop(&q);if(QueueEmpty(&q)){printf("队列已经为空\n");}else{printf("队列不为空\n");}QueueDestroy(&q);
}

完整代码

Queue.h

//链式结构:表示队列 typedef int QDataType;typedef struct QNode { struct QNode* next; QDataType data; }QNode; // 队列的结构 typedef struct Queue { QNode* front; QNode* rear; int size;}Queue; // 初始化队列 void QueueInit(Queue* q); // 队尾入队列 void QueuePush(Queue* q, QDataType data); // 队头出队列 void QueuePop(Queue* q); // 获取队列头部元素 QDataType QueueFront(Queue* q); // 获取队列队尾元素 QDataType QueueBack(Queue* q); // 获取队列中有效元素个数 int QueueSize(Queue* q); // 检测队列是否为空,如果为空返回非零结果,如果非空返回0 int QueueEmpty(Queue* q); // 销毁队列 void QueueDestroy(Queue* q);///void TestQueue();

Queue.c

#include"Queue.h"#include<stdio.h>
#include<assert.h>
#include<malloc.h>//申请一个节点
QNode* buyQNode(QDataType data)
{QNode *newnode=(QNode*)malloc(sizeof(QNode));if(NULL==newnode){assert(0);return NULL;}newnode->data=data;newnode->next=NULL;return newnode;
}//初始化队列 
void QueueInit(Queue* q)
{assert(q);q->front=q->rear=NULL;q->size=0;}
// 队尾入队列 
void QueuePush(Queue* q, QDataType data)
{assert(q);QNode *newnode=buyQNode(data);if(NULL==q->front){q->front=newnode; }else{q->rear->next=newnode; }q->rear=newnode;q->size++;
}
// 队头出队列 
void QueuePop(Queue* q)
{assert(q);if(QueueEmpty(q)){return;}else{QNode *delndoe=q->front;q->front=delndoe->next;free(delndoe);if(NULL==q->front){q->rear=NULL;}}q->size--;
}
// 获取队列头部元素 
QDataType QueueFront(Queue* q)
{assert(!QueueEmpty(q));return q->front->data;
}
// 获取队列队尾元素 
QDataType QueueBack(Queue* q)
{assert(!QueueEmpty(q));return q->rear->data;
}
// 获取队列中有效元素个数 
int QueueSize(Queue* q)
{assert(!QueueEmpty(q));return q->size;
}
// 检测队列是否为空,如果为空返回非零结果,如果非空返回0 
int QueueEmpty(Queue* q)
{assert(q);return NULL==q->front;
}
// 销毁队列 
void QueueDestroy(Queue* q)
{assert(q);QNode *cur=q->front;while(cur){q->front=cur->next;free(cur);cur=q->front;}q->rear=NULL;q->size=0;
}/
void TestQueue()
{Queue q;QueueInit(&q);QueuePush(&q, 1);QueuePush(&q, 2);QueuePush(&q, 3);QueuePush(&q, 4);QueuePush(&q, 5);printf("%d\n", QueueFront(&q));printf("%d\n", QueueBack(&q));printf("%d\n", QueueSize(&q));QueuePop(&q);QueuePop(&q);QueuePop(&q);printf("%d\n", QueueFront(&q));printf("%d\n", QueueBack(&q));printf("%d\n", QueueSize(&q));QueuePop(&q);QueuePop(&q);QueuePop(&q);if(QueueEmpty(&q)){printf("队列已经为空\n");}else{printf("队列不为空\n");}QueueDestroy(&q);
}

main.c

#include"Queue.h"int main()
{TestQueue();return 0;
}

三、环形队列

假溢出问题

  正常顺序队列若进行插入和删除,会使前部分的空间浪费,从而造成假溢出的情况。
在这里插入图片描述

  未解决假溢出的问题,大佬们提出了一种叫做环形队列的结构,环形队列可以使用数组实现,也可以使用循环链表实现。

在这里插入图片描述  判断循环队列是否为空或者满的问题,通常用(rear-front+N)%N的方法判断是否为满或空。
在这里插入图片描述


http://chatgpt.dhexx.cn/article/XPXWyc9S.shtml

相关文章

C#队列和栈的使用

一、队列 队列是其元素以先进先出&#xff08;Firstin,Firstout,FIFO&#xff09;的方式来处理的集合。先放入队列中的元素会先读取。队列使用System.Collections.Generic命名空间中的泛型类Queue<T>实现。 队列的成员 Count&#xff1a;Count属性返回队列中元素个数。…

栈和队列经典面试题

目录 1、括号匹配问题 2、用队列实现栈 3、用栈实现队列 4、设计循环队列 1、括号匹配问题 链接直达&#xff1a; 有效的括号 题目&#xff1a; 思路&#xff1a; 做题前&#xff0c;得先明确解题方案是啥&#xff0c;此题用栈的思想去解决是较为方便的&#xff0c;栈明确指…

栈stack和队列

栈和队列 一 栈和队列二 栈三.队列 一 栈和队列 栈和队列是两种重要的线性结构。从数据结构来看&#xff0c;栈和队列也是线性表&#xff0c;其特殊性在于栈和队列的基本操作是线性表操作的子集&#xff08;也具有顺序结构和链式结构&#xff09;&#xff0c;它们是操作受限的…

链表,队列和栈的区别

链表&#xff0c;队列和栈都是数据结构的一种。Sartaj Sahni 在他的《数据结构、算法与应用》一书中称&#xff1a;“数据结构是数据对象&#xff0c;以及存在于该对象的实例和组成实例的数据元素之间的各种联系。这些联系可以通过定义相关的函数来给出。”他将数据对象&#x…

栈与队列的定义与区别

1、栈 首先&#xff0c;普通的线性表实现是有两个端口可以访问的&#xff0c;但是如果作为栈就要封闭一端&#xff0c;只能访问另一端。这当然不是自讨苦吃&#xff0c;栈是一种抽象数据结构&#xff0c;是对现实世界对象的模拟。比如&#xff0c;自助餐厅中的一叠盘子&#x…

java 队列和栈的区别

栈和队列的区别 &#xff08;1&#xff09;数据插入删除 栈是一种特殊的线性表&#xff0c;他只能在一段进行插入和删除操作&#xff0c;就好像是一个井一样。进行数据插入和删除就类似于井口&#xff0c;称为栈定。而井也是有底部的&#xff0c;栈无法进行插入删除操作的这一…

监督学习和无监督学习的区别(机器学习)

机器学习主要分为两类 监督学习无监督学习 两者的区别主要是是否需要人工参与数据结果的标注 监督学习&#xff1a;教计算机如何去完成预测任务&#xff08;有反馈&#xff09;&#xff0c;预先给一定数据量的输入和对应的结果即训练集&#xff0c;建模拟合&#xff0c;最后让…

简单说下有监督学习和无监督学习的区别

简单说下有监督学习和无监督学习的区别 解析&#xff1a; 有监督学习&#xff1a;对具有标记的训练样本进行学习&#xff0c;以尽可能对训练样本集外的数据进行分类预测。&#xff08;LR,SVM,BP,RF,GBDT&#xff09; 无监督学习&#xff1a;对未标记的样本进行训练学习&#xf…

一个简单的例子来理解监督学习和非监督学习及其区别

首先&#xff0c;必须理解两个基本概念&#xff1a;特征值和目标值&#xff0c;先看图例 1、特征值&#xff1a; 特征值是指数据的特征&#xff0c;对于每个样本&#xff0c;通常具有一些 "属性"&#xff08;Attribute&#xff09;或者说 ”特征“&#xff08;Featu…

监督学习、无监督学习和半监督学习区别

1、概念 1.1监督学习&#xff08;数据集有输入和输出数据&#xff09;&#xff1a;通过已有的一部分输入数据与输出数据之间的相应关系。生成一个函数&#xff0c;将输入映射到合适的输出&#xff0c;比如分类。 1.2无监督学习&#xff08;数据集中只有输入&#xff09;&…

监督、自监督、半监督、无监督学习的区别

目录 一、简易版区别 二、详细版区别 一、简易版区别 A Survey on Semi-, Self-and Unsupervised Learning for Image Classification 文中的解释&#xff1a; 监督学习&#xff08;a&#xff09;&#xff1a;给出全部样本红蓝两类的标签 半监督学习&#xff08;b&#xf…

有监督学习与无监督学习

机器学习的常用方法&#xff0c;主要分为有监督学习(supervised learning)和无监督学习(unsupervised learning)。简单的归纳就是&#xff0c;是否有监督&#xff08;supervised&#xff09;&#xff0c;就看输入数据是否有标签&#xff08;label&#xff09;。输入数据有标签&…

有监督和无监督

来自有监督vs.无监督&#xff0c;傻傻分不清楚&#xff1f; - 搜狐网 网上对于有监督和无监督差异性的文章非常多&#xff0c;本文将重点从应用的角度来阐述如何选择有监督和无监督。 对比一&#xff1a;有标签 vs. 无标签 有监督又被称为“有老师的学习”&#xff0c;无监督被…

机器学习:有监督和无监督之间有什么区别

机器学习是人工智能的一个子集&#xff0c;它通过示例和经验教会计算机执行任务&#xff0c;是研究和开发的热门领域。我们每天使用的许多应用程序都使用机器学习算法&#xff0c;包括AI助手&#xff0c;Web搜索和机器翻译。 您的社交媒体新闻提要由机器学习算法提供支持。您、…

有监督学习与无监督学习的几大区别

当下无监督作为一种热门的机器学习技术&#xff0c;网上有不少关于无监督与有监督差异讨论的文章。DataVisor作为率先将无监督技术运用在反欺诈行业的娇娇领先者&#xff0c;我们在本文中&#xff0c;将深入浅出的讲解无监督机器学习技术与有监督技术在不同方面的区别&#xff…

监督学习和无监督学习区别

前言 机器学习分为&#xff1a;监督学习&#xff0c;无监督学习&#xff0c;半监督学习&#xff08;也可以用hinton所说的强化学习&#xff09;等。 在这里&#xff0c;主要理解一下监督学习和无监督学习。 监督学习&#xff08;supervised learning&#xff09; 从给定的训…

关于使用burpsuite时,“安全连接失败,使用了无效的证书”问题【已解决】

安装好burpsuite&#xff0c;配置好网络连接代理后&#xff0c;导入了证书&#xff0c;访问某一网站还是会出现如下现象&#xff1a; 解决方案&#xff1a; 打开浏览器设置-高级-证书-证书机构&#xff0c;删除刚才导入的证书。 再次访问http:\burp下载证书。 再次在设置-高级…

火狐浏览器出现“建立安全连接失败”PR_CONNECT_RESET_ERROR解决方法

访问一个网站出现这样的问题&#xff0c;可能是因为自己设置一些东西导致DNS解析出错。 我找了网上几个比较主流的方法都不能解决&#xff0c;最后就是一招刷新DNS解决了。&#xff08;哭笑不得&#xff09; 解决方法&#xff1a; 按“win R”键&#xff0c;启动运行窗口&a…

Horizon client连接错面报错:无法建立安全加密链路连接

一、问题描述 前方人员反馈在Horizon环境中交付桌面前&#xff0c;验证过程中&#xff0c;使用Horizon client登录错误报&#xff1a;无法建立安全加密链路连接&#xff0c;如下图所示&#xff1a; UAG软件版本&#xff1a;3.9 二、分析处理 1、检查客户端SSL配置选项&…