news 2026/10/20 12:07:06

栈与队列和数组(下)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
栈与队列和数组(下)

逆波兰表达式(补)

思路:可以直接建立一个大的数组作为栈,开始遍历字符串数据,当遇到数字的时候就把值存在新建的数组中吗,遇到运算符号就弹出两个值进行运算,之后又将字存在新建的数组中。

注意:1.int、char、short、long都是整型。在使用字符型的时候需要加上单引号。在里面很容易将字符打错。2.算完一次运算后需要将数据重新压回栈中

bool evalbool(char* tokens){ if(tokens[0]<='9'&&tokens[0]>='0'){// return true; } if(tokens[0]=='-'&&tokens[1]<='9'&&tokens[1]>='0'){ return true; } return false; } int evalRPN(char** tokens, int tokensSize) { int stackarr[10000]; int j=0; int sum=0; for(int i=0;i<tokensSize;i++){ if(evalbool(tokens[i])){// int mun =atoi(tokens[i]);// stackarr[j]=mun; j++; } else{ int right=stackarr[--j]; int left=stackarr[--j]; switch(tokens[i][0]){//这里可以看成一个二位数组的 case '+':sum=right+left; break; case '-':sum=left-right; break; case '*':sum=left*right; break; case '/':sum=left/right; break; } stackarr[j++]=sum;// } } return stackarr[0]; }

重点:二级指针的运用

二级指针是指向指针的指针,即一个指针变量存储的是另一个指针变量的地址。在逆波兰表达式的实现中,二级指针常用于在函数内部修改传入的指针本身,从而让栈顶指针的更新能够反映到调用方。

例如,当使用链表实现栈时,入栈操作需要修改栈顶指针 top 的指向。如果直接传入一级指针,函数内部对 top 的修改无法传回调用方;而传入二级指针(即 &top),函数内部通过 *top 就能修改调用方的 top 变量,从而正确维护栈顶。

典型写法如下:

void push(Node **top, int value) { Node *newNode = (Node *)malloc(sizeof(Node)); newNode->data = value; newNode->next = *top; *top = newNode; // 通过二级指针修改调用方的栈顶指针 } int pop(Node **top) { if (*top == NULL) return -1; Node *temp = *top; int value = temp->data; *top = temp->next; free(temp); return value; }

使用二级指针时需要注意:调用处必须传入栈顶指针的地址,即 &top;函数内部对 *top 的赋值会直接改变调用方的指针值。这样可以避免返回值传递的繁琐,也让代码更贴近底层指针操作的语义。

队列

队列是限定在一端插入、另一端删除的线性表,遵循先进先出(FIFO)原则。入队是在队尾进行插入,出队是在队头进行删除。实现队列时,通常采用链式存储或顺序存储两种方式。

链式存储实现队列的要点

链式存储使用链表节点保存数据,每个节点包含数据域和指向下一个节点的指针。实现时需要注意以下几点:

  • 带头节点(哨兵位):推荐使用带头节点的单链表,头节点不存储数据,便于统一处理空队列和首元素入队的情况。
  • 维护 front 和 rear 指针:front 指向队头节点,rear 指向队尾节点。入队时在 rear 之后插入新节点并更新 rear;出队时删除 front 指向的节点并更新 front。
  • 出队时注意 rear 指针:当队列中只剩一个节点时,出队后 front 和 rear 都会变为空,此时必须将 rear 也置为 NULL,否则 rear 会变成野指针。
  • 判空条件:front 和 rear 都为空(或 front 指向头节点且 rear 指向头节点)时队列为空。
  • 内存管理:出队删除节点后需要释放内存,避免内存泄漏。

顺序存储实现队列的要点

顺序存储使用数组保存数据,通过 front 和 rear 两个下标来标记队头和队尾。实现时需要注意以下几点:

  • 假溢出问题:普通顺序队列中,rear 到达数组末尾时即使数组前面还有空闲空间,也无法继续入队,这就是假溢出。
  • 解决假溢出:使用循环队列,让 rear 和 front 在到达数组末尾时回绕到数组开头。
  • 判空与判满:循环队列中,判空条件为 front == rear;判满条件为 (rear + 1) % MaxSize == front,即牺牲一个存储单元来区分空和满。
  • 元素个数计算:队列中元素个数为 (rear - front + MaxSize) % MaxSize。
  • 入队操作:先判断是否满,不满则存入 data[rear],再执行 rear = (rear + 1) % MaxSize。
  • 出队操作:先判断是否空,不空则取出 data[front],再执行 front = (front + 1) % MaxSize。

循环队列相关知识点

循环队列是顺序队列的改进,通过取模运算让 rear 和 front 在数组范围内循环移动,从而充分利用数组空间。核心知识点如下:

  • 基本结构:使用数组 data[MaxSize] 存储元素,front 指向队头元素,rear 指向队尾元素的下一个位置。
  • 入队:rear = (rear + 1) % MaxSize,然后将元素存入 data[rear]。
  • 出队:取出 data[front],然后 front = (front + 1) % MaxSize。
  • 判空:front == rear。
  • 判满:1.牺牲一个空间:(rear + 1) % MaxSize == front,此时数组中实际最多存储 MaxSize - 1 个元素。 2.通过计数的方式来判断是空还是满。
  • 队列长度:(rear - front + MaxSize) % MaxSize。
  • 应用场景:循环队列常用于操作系统中的缓冲区管理、生产者消费者模型、以及需要固定容量且频繁入队出队的场景。

队列的应用

这可以使用带有头节点的队列,这样可以方便插入,但是在删除的时候需要分情况讨论1.当队列中只有一个元素时,rear指针指与front指针指向同一位置;2.队列中元素不止有一个,这时直接进行头删即可

实现是会出现的问题:1.在执行的个个函数的时候需要检查队列是否是空队列。2.在销毁队列中:进行while循环释放队列的条件中:不能使用cur->next条件,这样的会跳过cur不空的情况;front和rear都需要置为空。3.把队列销毁后,使用打印函数会发生访问权限冲突。

#pragma once #include<assert.h> #include<stdlib.h> #include<stdio.h> typedef int QDataType; typedef struct QListNode { struct QListNode* _next; QDataType _data; }QNode; typedef struct Queue { QNode* _front; QNode* _rear; int size; }Queue; // 初始化队列 void QueueInit(Queue* q) { assert(q); q->_front = q->_rear = (QNode*)malloc(sizeof(QNode));//这里是为了创建一个节点 if (q->_front==NULL && q->_rear==NULL) { printf("creat shibai\n"); exit(-1); } q->_front->_next = NULL; q->size = 0; } // 队尾入队列 ,像是尾插 void QueuePush(Queue* q, QDataType data) { assert(q); QNode*pnew=(QNode*)malloc(sizeof(QNode)); pnew->_data = data; pnew->_next = NULL; q->_rear->_next = pnew; q->_rear = pnew; q->size++; } void PrintfQueue(Queue* q) { assert(q); QNode* cur = q->_front->_next; while (cur) { printf("%d-> ", cur->_data); cur = cur->_next; } printf("\n"); } // 队头出队列 void QueuePop(Queue* q) { QNode* cur = q->_front->_next; q->_front->_next = cur->_next; free(cur); } // 获取队列头部元素 QDataType QueueFront(Queue* q) { return q->_front->_next->_data; } // 获取队列队尾元素 QDataType QueueBack(Queue* q) { QNode* cur = q; while (cur->_next) { cur = cur->_next; } return cur->_data; } // 获取队列中有效元素个数 int QueueSize(Queue* q) { QNode* cur = q->_front; int num = 0; while (cur && cur->_next) { num++; cur = cur->_next; } return num; } // 检测队列是否为空,如果为空返回非零结果,如果非空返回0 int QueueEmpty(Queue* q) { if (q->_front->_next == NULL) { return 1; } return 0; } // 销毁队列 void QueueDestroy(Queue* q) { assert(q); QNode* cur = q->_front; while (cur) { QNode* pro = cur->_next; free(cur); cur = pro; } q->_front = NULL; q->_rear = NULL; q->size = 0; }
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/20 12:07:06

STM32通过IIC驱动INA226的电流监测实战:从寄存器配置到校准换算

简介&#xff1a;这份资源面向嵌入式开发者和电子爱好者&#xff0c;讲解基于 STM32 微控制器通过 IIC 总线协议驱动 INA226 高精度电流电压监测芯片的完整实现方案。内容包含 INA226 工作原理、内部寄存器配置方法&#xff08;如采样电阻、电压量程、测量频率&#xff09;、II…

作者头像 李华
网站建设 2026/10/20 12:03:55

基于websocket++的C++ WebSocket通信demo与二次开发实战

简介&#xff1a;基于WebSocket构建的客户端与服务端示例代码包&#xff0c;面向需要在C项目中快速实现实时双向通信的开发者&#xff0c;尤其适合结合Boost在Windows环境下搭建WebSocket应用的初学者。压缩包共2000个文件&#xff0c;大小约320.48MB&#xff0c;内容以hpp头文…

作者头像 李华
网站建设 2026/10/20 12:02:58

从问题解答到投诉处理:智能客服系统设计要点全解析

我先说结论&#xff1a;这个标题看起来不大&#xff0c;但真做起来坑非常多。很多人以为智能客服就是把常见问题丢给机器人自动回复&#xff0c;配上几个关键词匹配就完事&#xff0c;等投诉量一上来才发现&#xff0c;机器人答非所问、情绪升级、转人工不畅&#xff0c;全堆在…

作者头像 李华
网站建设 2026/10/20 12:01:20

Spark读写HDFS、HBase与JSON:选型、调优与避坑实战

1. 为什么要在Spark里同时搞定HDFS、HBase和JSON大数据处理绕不开三件事&#xff1a;数据从哪来、怎么算、算完往哪放。Spark本身是个计算引擎&#xff0c;它不存数据&#xff0c;所以读写外部存储就成了日常开发里最高频的操作。我做过一个统计&#xff0c;一个典型的数据管道…

作者头像 李华
网站建设 2026/10/20 12:01:16

AD密码到期与账户锁定怎么办?三招实现自动化排查与处理

1. 问题场景还原&#xff1a;AD密码到期锁定到底有多烦先别急着看操作&#xff0c;我先把场景还原一下。做企业IT运维的兄弟应该都有这种体验&#xff1a;某天早上刚坐下&#xff0c;邮箱里已经躺着七八封密码过期提醒&#xff0c;紧接着Helpdesk电话就开始响个不停。用户那头永…

作者头像 李华
网站建设 2026/10/20 12:01:06

Hadoop集群运维实战:HDFS与YARN核心原理、配置调优及故障排查

1. 从单机到集群&#xff1a;Hadoop到底解决了什么运维难题很多刚接触企业级运维的朋友会有个疑问&#xff1a;现在单机服务器动辄几十核、上百G内存&#xff0c;数据库性能也很强&#xff0c;为什么还要搞Hadoop这套分布式系统&#xff1f;我刚开始做运维的时候也有这个困惑&a…

作者头像 李华