C/C++栈和队列

news2024/10/22 4:47:31

一.队列

结构定义

FIFO:队列是一个先进先出的数据结构;

只允许从队首出元素,从队尾入元素;

head和tail所包含的区间是左闭开的;

入队操作

没用真实将一号元素删除,而是将head指针向后移动一位,进行逻辑上的删除;

出队操作

将新元素储存在队尾指针所在的位置,并将队尾指针向后移动一位;

队列的假溢出

有三个空位,但是tail超出范围;

此时可以引入循环队列:当tail超出范围时让tail重新指向0;

循环队列

解决了队列的假溢出问题;

代码实现

链表的顺序表实现:

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<time.h>

typedef struct Vector {
	int* data;
	int size; 
}vector;

vector* initVector(int n) {
	vector* v = (vector*)malloc(sizeof(vector));
	v->size = n;
	v->data = (int*)malloc(n * sizeof(int));
	return v;
}

void clearVector(vector* v) {
	if (v == NULL) return;
	free(v->data);
	v->data = NULL;
	free(v);
	v = NULL;
	return;
}

int vectorSeek(vector* v,int pos) {
	if (pos < 0 || pos >= v->size) return -1;
	return v->data[pos];
}

int insertVector(vector* v, int pos, int val) {
	if (pos < 0 || pos >= v->size) return -1;
	v->data[pos] = val;
	return 1;
}

typedef struct Queue {
	vector* data;
	int size, head, tail, count;
}Queue;

Queue* initQueue(int n) {
	Queue* q = (Queue*)malloc(n * sizeof(Queue));
	q->data = initVector(n);
	q->count = q->head = q->tail = 0;
	q->size = n;
	return q;
}//初始化大小为n的队列

void clearQueue(Queue* q) {
	if (q == NULL) return;
	clearVector(q->data);
	free(q);
	q = NULL;
	return;
}

int empty(Queue* q) {
	return q->count == 0;
}//判断队列是否是空的

int push(Queue* q, int val) {
	if (q->count == q->size) return 0;
	insertVector(q->data, q->tail, val);
	q->tail += 1;
	if (q->tail == q->size) q->tail = 0;
	q->count += 1;
	return 1;
}//压入队尾元素
//返回值代表是否push成功

int front(Queue* q) {
	return vectorSeek(q->data, q->head);
}//查看队首元素

int pop(Queue* q) {
	if (empty(q)) return 0;
	q->head += 1;
	if (q->head == q->size) q->head = 0;
	q->count -= 1;
	return 1;
}//弹出队首元素,返回0代表不成功	

void outputQueue(Queue* q) {
	printf("Queue:\n");
	for (int i = 0; i < q->count; i++) {
		printf("%4d", vectorSeek(q->data, (q->head + i) % q->size));
	}
	printf("\n");
	return;
}

int main() {
	srand(time(0));
#define MAX_OP 10
	Queue* q = initQueue(5);
	for (int i = 0; i < MAX_OP; i++) {
		int op = rand() % 5, val = rand() % 100;//1234 push,0 pop
		switch (op) {
			case 0:
				printf("front of q:%d\n", front(q));
				pop(q);
				break;
			case 1:
			case 2:
			case 3:
			case 4:
				printf("push %d to q\n", val);
				push(q, val);
				break;
		}
		outputQueue(q);
	}
	return 0;
}

链表的链表实现:

不存在队列假溢出问题,不用再使用循环链表了,size参数可以省略;

但是可以再记录count来判断队列是否为空队列;

队列的头尾指针可以被省略;

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<time.h>

typedef struct Node {
	int data;
	Node* next;
}Node;

typedef struct LinkList{
	Node head, *tail;//注意这里实现的是有头链表,head并不存储数据
	int size;
}LinkList;

LinkList* initLinkList() {
	LinkList* l = (LinkList*)malloc(sizeof(LinkList));
	l->head.next = NULL;
	l->tail = &(l->head);
	return l;
}

void clearLinkList(LinkList* l) {
	Node* p = l->head.next, *q;
	while (p) {
		q = p;
		p = p->next;
		free(q);
		q = NULL; 
	}
	free(l);
	l = NULL;
}


int frontList(LinkList* l) {
	if (l->head.next == NULL) return 0;
	return l->head.next->data;
}

Node* getNewNode(int val) {
	Node* node = (Node*)malloc(sizeof(Node));
	node->data = val;
	node->next = NULL;
	return node;
}

int insertTail(LinkList* l, int val) {
	Node* node = getNewNode(val);
	l->tail->next = node;
	l->tail = node;
	return 1;
}

int emptyList(LinkList* l) {
	return l->head.next == NULL;
}

int eraseHead(LinkList* l) {
	if (emptyList(l)) return 0;
	Node* p = l->head.next;
	l->head.next = l->head.next->next;
	if (p == l->tail) l->tail = &(l->head);
	free(p);
	return 1;
}

typedef struct Queue {
	LinkList* l;
	int count;
}Queue;

Queue* initQueue(int n) {
	Queue* q = (Queue*)malloc(n * sizeof(Queue));
	q->l = initLinkList();
	q->count = 0;
	return q;
}//初始化大小为n的队列

void clearQueue(Queue* q) {
	if (q == NULL) return;
	clearLinkList(q->l);
	free(q);
	q = NULL;
	return;
}

int empty(Queue* q) {
	return q->count == 0;
}//判断队列是否是空的

int push(Queue* q, int val) {
	insertTail(q->l, val);
	q->count += 1;
	return 1;
}//压入队尾元素
//返回值代表是否push成功

int front(Queue* q) {
	if (empty(q)) return -1;//代表查找首元素失败
	return frontList(q->l);
}//查看队首元素

int pop(Queue* q) {
	if (empty(q)) return 0;
	eraseHead(q->l);
	q->count -= 1;
	return 1;
}//弹出队首元素,返回0代表不成功	

void outputQueue(Queue* q) {
	printf("Queue:\n");
	Node* p = q->l->head.next;
	for (int i = 0; i < q->count; i++) {
		printf("%4d", p->data);
		p = p->next;
	}
	printf("\n");
	return;
}


int main() {
	srand(time(0));
#define MAX_OP 10
	Queue* q = initQueue(5);
	for (int i = 0; i < MAX_OP; i++) {
		int op = rand() % 5, val = rand() % 100;//1234 push,0 pop
		switch (op) {
		case 0:
			printf("front of q:%d\n", front(q));
			pop(q);
			break;
		case 1:
		case 2:
		case 3:
		case 4:
			printf("push %d to q\n", val);
			push(q, val);
			break;
		}
		outputQueue(q);
	}
	return 0;
}

二.栈

结构定义

栈是一种先进后出(FILO)的数据结构;

出栈操作

入栈操作

代码实现

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<time.h>

typedef struct Stack {
	int* data;
	int size, top;
}Stack;

Stack* initStack(int n) {
	Stack* s = (Stack*)malloc(sizeof(Stack));
	s->data = (int*)malloc(n * sizeof(Stack));
	s->size = n;
	s->top = -1;//!!!
	return s;
}

void clearStack(Stack* s) {
	if (s == NULL) return;
	free(s->data);
	s->data = NULL;
	free(s);
	s = NULL;
	return;
}

int empty(Stack* s) {
	return (s->top == 1);
}

int top(Stack* s) {
	if (empty(s)) return 0;
	return s->data[s->top];
}

int push(Stack* s, int val) {
	if (s->top + 1 == s->size) return 0;
	s->top += 1;
	s->data[s->top] = val;
	return 1;
}

int pop(Stack* s) {
	if (empty(s)) return 0;
	s->top -= 1;
	return 1;
}

void outputStack(Stack* s) {
	printf("Stack:");
	for (int i = s->top; i >= 0; i--) {
		printf("%4d", s->data[i]);
	}
	printf("\n\n");
	return;
}

int main() {
	srand(time(0));
#define MAX_OP 10
	Stack* s = initStack(5);
	for (int i = 0; i < MAX_OP; i++) {
		int op = rand() % 3;//0 pop;1 2 push;
		int val = rand() % 100;
		switch (op) {
		case 0:
			printf("pop Stack, item = %d\n", top(s));
			pop(s);
			break;
		case 1:
		case 2:
			printf("push Stack, item = %d\n", val);
			push(s, val);
			break;
		}
		outputStack(s);
	}
	return 0;
}

题目练习

20. 有效的括号 - 力扣(LeetCode)

class Solution {
public:
    bool isValid(string s) {
        int n = s.size();
        //if(n % 2) return false;
        unordered_map<char, char> pairs = {
            {')', '('},
            {']', '['},
            {'}', '{'}
        };
        stack<char> stk;
        for(char ch: s) {
            if(pairs.count(ch)) {
                if(stk.empty() || stk.top() != pairs[ch]) {
                    return false;
                }
                stk.pop();
            }
            else {
                stk.push(ch);
            }
        }
        return stk.empty();
    }
};

栈的深入理解:

思考:如果简化成只有一种括号,不用栈怎么实现上述题目的要求.

结论:

1.在任意一个位置上,左括号数量>=右括号数量;

2.在最后一个位置上,左括号数量==右括号数量;

3.程序中只需要记录左右括号的数量即可;

其中lnum的作用相当于栈顶指针top;

思考:

1.+1可以等价为进,-1可以等价为出;

2.一对()可以看成完整的一个事件;

3.(())可以看成事件与事件之间的完全包含关系;

4.由括号的等价变换,得到了一个新的数据结构;

栈:可以处理具有完全包含关系的问题.

三.栈和队列的应用

刷题记录

程序调用关系 - 题目 - Online Judge (haizeix.com)

//#define _CRT_SECURE_NO_WARNINGS

#include <iostream>
#include <cstdio>
#include <queue>

#include <string>
#include <vector>

using namespace std;


int main(){
	int n;
	int flag = 0;
	cin >> n;
	vector<string> ops(n), s;
	string target;
	for (int i = 0; i < n; i++) cin >> ops[i];
	cin >> target;
	for (int i = 0; i < n; i++) {
		if (target == ops[i]) {
			s.push_back(ops[i]);
			flag = 1;
			break;
		}
		if (ops[i] == "return") {
			s.pop_back();
		}
else {
	s.push_back(ops[i]);
}
}
if (flag) {
	for (int i = 0; i < s.size(); i++) {
		if (i) { cout << "->"; }
		cout << s[i];
	}
	cout << endl;
}else {
	cout << "NOT REFERENCED" << endl;
}
return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2213718.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

二校区图书馆一楼《中华再造善本》很多

上两幅为同一本书的&#xff0c;有“太平之时嫌官小&#xff0c;离乱之时怕出征”这句 上两幅为同一本书的&#xff0c;为《水浒传》节选 二校区图书馆一楼满眼都是线装的古书《中华再造善本》 图书馆五楼 图书馆四楼&#xff0c;一个人躺在长沙发上 图书馆一楼的透明电梯

Intel Xeon(至强) 服务器 CPU

Purley平台&#xff1a;Sky Lake&#xff08;第一代&#xff09;、Cascade Lake&#xff08;第二代&#xff09; Whitley平台&#xff1a;Cooper Lake、Ice Lake&#xff08;第三代&#xff09; Eagle Stream平台&#xff1a;Sapphire Rapids、Emerald Rapids&#xff08;第四…

Vite打包碎片化,如何化解?

背景 我们在使用Vite进行打包时&#xff0c;经常会遇到这个问题&#xff1a;随着业务的展开&#xff0c;版本迭代&#xff0c;页面越来越多&#xff0c;第三方依赖也越来越多&#xff0c;打出来的包也越来越大。如果把页面都进行动态导入&#xff0c;那么凡是几个页面共用的文…

RHCSA的学习(5)

一、文本内容处理命令 1、数据流和重定向 1、数据流 标准输入&#xff08;standard input&#xff0c;简称stdin&#xff09;&#xff1a;默认情况下&#xff0c;标准输入指从键盘获取的输入标准输出&#xff08;standard output&#xff0c;简称stdout&#xff09;&#xff…

2020前端面试 - JavaScript2.0篇

前言&#xff1a; 个人觉得面试其实是一个自我学习的过程&#xff0c;如果说短时间内找不到工作&#xff0c;那一定是你面的还不够多&#xff0c;不要气馁&#xff0c;不要放弃&#xff0c;在心底告诉自己&#xff0c;下一次面试&#xff0c;再下一次面试&#xff0c;一定能够拿…

为什么inet_ntoa会返回错误的IP地址?

目录 1、调用inet_addr和inet_ntoa实现整型IP与点式字符串之间的转换 1.1、调用inet_addr将点式字符串IP转换成整型IP 1.2、调用inet_ntoa将整型IP转换成点式字符串IP 2、调用inet_ntoa返回错误点式字符串IP的原因分析 3、解决多线程调用inet_ntoa返回错误点式字符串IP的办…

在 Docker容器中安装 ROS-Melodic 并使用 rviz 进行图形化显示

文章目录 写在前面1. 背景描述2. 安装步骤2.1 允许本地机器上的用户或进程连接到 X server2.2 拉取 docker 镜像2.3 使用镜像osrf/ros:melodic-desktop-full创建并运行容器2.4 运行 roscore2.5 运行 rviz 参考链接 写在前面 自己的测试环境&#xff1a; Ubuntu20.04&#xff0…

基于SSM的微信小程序博客管理系统(博客1)

&#x1f449;文末查看项目功能视频演示获取源码sql脚本视频导入教程视频 1、项目介绍 基于SSM的微信小程序博客管理系统实现与设计&#xff0c;实现了管理员与用户&#xff0c;管理员实现了用户管理、博文信息管理、博文类型管理、我的博文管理、个人名片分享管理、签到管理…

SAP S/4 HANA 销售返利

目录 1 简介 2 后台配置 3 主数据 4 业务操作 4.1 场景 1 - 返利应计 4.2 场景 2 - 最终结算 1 简介 在过去 SAP ECC 把“返利”功能集成在了 SD 模块当中&#xff0c;而 SAP S/4 HANA 把“返利”集成在了结算管理功能模块当中。究其原因&#xff0c;主要是 ECC “返利”…

深度解析LMS(Least Mean Squares)算法

目录 一、引言二、LMS算法简介三、LMS算法的工作原理四、LMS算法的特点五、LMS算法的应用场景六、LMS算法的局限性七、总结八、进一步探讨 一、引言 自适应滤波器是一种动态调整其参数以适应变化环境的信号处理工具&#xff0c;广泛应用于噪声消除、信道均衡和系统识别等领域。…

算法工程师重生之第二十五天(加油站 分发糖果 柠檬水找零 根据身高重建队列 )

参考文献 代码随想录 一、加油站 在一条环路上有 n 个加油站&#xff0c;其中第 i 个加油站有汽油 gas[i] 升。 你有一辆油箱容量无限的的汽车&#xff0c;从第 i 个加油站开往第 i1 个加油站需要消耗汽油 cost[i] 升。你从其中的一个加油站出发&#xff0c;开始时油箱为空。…

Mysql的Innodb的RR隔离级别到底有没有解决幻读问题?

InnoDB中的repeatable read这种隔离级别通过间隙锁MVCC解决了大部分的幻读问题&#xff0c;但是并不是所有的幻读都能解读&#xff0c;想要彻底解决幻读&#xff0c;需要使用Serializable的隔离级别。 MVCC解决幻读 在RC中&#xff0c;每次读取都会重新生成一个快照&#xff…

EDM平台排行榜与工具推荐

本文总结了EDM平台排行榜&#xff0c;包括ZohoCampaigns、Mailchimp等。各平台在集成性、自动化、模板库等方面各具优势&#xff0c;适合不同规模和需求的企业。选择适合的EDM平台对营销活动成功至关重要。 1. Zoho Campaigns 简介 Zoho Campaigns是Zoho的edm平台&#xff0c…

[LeetCode] 515. 在每个树行中找最大值

题目描述&#xff1a; 给定一棵二叉树的根节点 root &#xff0c;请找出该二叉树中每一层的最大值。 示例1&#xff1a; 输入: root [1,3,2,5,3,null,9] 输出: [1,3,9]示例2&#xff1a; 输入: root [1,2,3] 输出: [1,3]提示&#xff1a; 二叉树的节点个数的范围是 [0,10…

标准地图下载

官网&#xff0c;地图来源为中国地图出版社、国家基础地理信息中心 http://bzdt.ch.mnr.gov.cn/ 能够下载各个版本的中国地图 世界地图

python中的工具

一、Scapy Scapy是python语言编写的工具&#xff0c;也是一个强大的交付式数据包处理程序&#xff0c;能够伪造或者解码大量的网络协议数据包&#xff0c;能够发送、嗅探、剖析和伪造网络数据包&#xff0c;如端口扫描、路由跟踪、探测、攻击或网络发现等。 python3环境下&am…

2022年华为杯数学建模竞赛B题论文和代码

基于整数规划的方形件排样和组批优化问题研究 常见的板式产品如玻璃&#xff0c;PCB板&#xff0c;铝合金门窗等产品因其结构定制化程度高的特点&#xff0c;相关生产制造的企业往往采用“多品种小批量”的个性化生产模式。通过对客户订单的组批&#xff0c;预先规划好各个产品…

【2022统考真题】计算时间复杂度

目录 一、题目描述 二、思路分析 三、易错提醒 四、同级和嵌套的关系 一、题目描述 下列程序段的时间复杂度是&#xff08;&#xff09; int sum 0; for (int i 1; i < n; i * 2) for (int j 0; j < i; j) sum; A. O(logn) B. O(n) C. O(nlogn) D…

卡牌小程序开发,线上抽卡机的优势

今年以来&#xff0c;卡牌成为了一种新的潮玩方式&#xff0c;继盲盒后在度成为大众收藏娱乐的选择。卡牌的种类各异&#xff0c;以热门IP为原型&#xff0c;设计出了专属卡牌&#xff0c;具有较大的收藏价值&#xff0c;吸引了无数的消费者的关注。 随着互联网技术的发展&…

python常用的字符串方法

一、求字符串的长度 python最常用的内置函数 二、切片获取子串 获取前第5个字符 print(s[:5]) # wuzij 获取后6个字符 print(s[-6:]) # python 三、去掉多余空格 四、是否以某个串开头 五、是否包含某个子串 六、串联多串 七、分割多串 八、替换子串