(C语言)队列实现与用队列实现栈

news2024/9/20 8:50:57

目录

1.队列

1.1队列的概念及结构

1.2 队列的实际应用联想

1.3队列的实现

2. 队列应用——队列实现栈

主要思路


1.队列

1.1队列的概念及结构

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

1.2 队列的实际应用联想

1. 基于队列的特点--先进先出,可以联想到大厅服务中的叫号机先到的先拿号,先拿号的先办业务,队列中的人是在等的人,办完业务为出队列,取号为如队列。

2. 也可以是查找和自己间接相关的人,像是查找qq好友的好友,开始自己在队列中,后来将自己出队列,将自己好友入队列,再将队列中的人出来,他们的好友再入队列,当然入队列的时候肯定有限制,不能是和之前重复的,以此类推,即可知道和自己外围相关的人,

注(仅为有代码新人的有端联想,不一定真正适合这些情况)

1.3队列的实现

队列也可以数组和链表的结构实现,使用链表的结构实现更优一些,因为如果使用数组的结构,出队列在数组头上出数据,效率会比较低。
下面我们来实现队列:
分两个文件:Queue.h与Queue.c
Queue.h进行头文件和函数的声明,以及队列结构的创建
#pragma once
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <stdbool.h>

//方便后面对不同数据的操作
typedef int QDataType;

//链式队列-队列结点结构体
typedef struct QListNode
{
	QDataType _data;
	struct	QListNode* _pnext;
}QNode;

//队列结构体
typedef struct Queue
{
	QNode* _phead;
	QNode* _ptail;
	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 
bool QueueEmpty(Queue* q);
// 销毁队列
void QueueDestroy(Queue* q);

Queue.c进行队列相关函数的实现

#include "Queue.h"

//队列初始化
void QueueInit(Queue* pst)
{
	assert(pst);
	pst->_phead = pst->_ptail = NULL;
	pst->_size = 0;
}

// 队尾入队列
void QueuePush(Queue* pst,QDataType x)
{
	assert(pst);

	QNode* newnode = (QNode*)malloc(sizeof(QNode));
	newnode->_data = x;
	newnode->_pnext = NULL;
	if (pst->_phead == NULL)
	{
		pst->_phead = pst->_ptail = newnode;
	}
	else
	{
		pst->_ptail->_pnext = newnode;
		pst->_ptail = newnode;
	}
	pst->_size++;
}

// 队头出队列
void QueuePop(Queue* pst)
{
	assert(pst);
	assert(pst->_size);
	QNode* next = pst->_phead->_pnext;
	free(pst->_phead);
	pst->_phead = next;
	pst->_size--;
}

// 获取队列队尾元素
QDataType QueueBack(Queue* pst)
{
	assert(pst);
	assert(pst->_size);
	return pst->_ptail->_data;
}

// 获取队列头部元素
QDataType QueueFront(Queue* pst)
{
	assert(pst);
	assert(pst->_size);
	return pst->_phead->_data;
}

// 获取队列中有效元素个数
int QueueSize(Queue* pst)
{
	assert(pst);
	return pst->_size;
}

// 检测队列是否为空,如果为空返回True,如果非空返回False 
bool QueueEmpty(Queue* pst)
{
	assert(pst);
	return pst->_size == 0;
}

// 销毁队列
void QueueDestroy(Queue* pst)
{
	assert(pst);
	QNode* cur = pst->_phead;
	while (cur)
	{
		QNode* next = cur->_pnext;
		free(cur);
		cur = next;
	}
	pst->_size = 0;
	pst->_phead = pst->_ptail = NULL;
}

2. 队列应用——队列实现栈

225. 用队列实现栈 - 力扣(LeetCode)

题目:

我们用直接使用前队列的代码实现栈。

主要思路

创建两个队列相互导数据实现后进先出的效果,;压数据时直接在有数据的那个队列中插入数据,出栈时将有数据的队列中的size-1个数据导入另一个队列里,则第一个队列中剩下的那个数据是我们要出栈的数据,这就是主要思路。

下面是代码演示:(代码有点长但是前面的大部分都是前面实现队列的代码,直接复制粘贴的)

typedef int QDataType;
// 链式队列-队列结点结构体
typedef struct QListNode {
    QDataType _data;
    struct QListNode* _pnext;
} QNode;

// 队列结构体
typedef struct Queue {
    QNode* _phead;
    QNode* _ptail;
    int _size;
} Queue;

// 队列初始化
void QueueInit(Queue* pst) {
    assert(pst);
    pst->_phead = pst->_ptail = NULL;
    pst->_size = 0;
}

// 队尾入队列
void QueuePush(Queue* pst, QDataType x) {
    assert(pst);

    QNode* newnode = (QNode*)malloc(sizeof(QNode));
    newnode->_data = x;
    newnode->_pnext = NULL;
    if (pst->_phead == NULL) {
        pst->_phead = pst->_ptail = newnode;
    } else {
        pst->_ptail->_pnext = newnode;
        pst->_ptail = newnode;
    }
    pst->_size++;
}

// 队头出队列
void QueuePop(Queue* pst) {
    assert(pst);
    assert(pst->_size);
    QNode* next = pst->_phead->_pnext;
    free(pst->_phead);
    pst->_phead = next;
    pst->_size--;
}

// 获取队列队尾元素
QDataType QueueBack(Queue* pst) {
    assert(pst);
    assert(pst->_size);
    return pst->_ptail->_data;
}

// 获取队列头部元素
QDataType QueueFront(Queue* pst) {
    assert(pst);
    assert(pst->_size);
    return pst->_phead->_data;
}

// 获取队列中有效元素个数
int QueueSize(Queue* pst) {
    assert(pst);
    return pst->_size;
}

// 检测队列是否为空,如果为空返回True,如果非空返回False
bool QueueEmpty(Queue* pst) {
    assert(pst);
    return pst->_size == 0;
}

// 销毁队列
void QueueDestroy(Queue* pst) {
    assert(pst);
    QNode* cur = pst->_phead;
    while (cur) {
        QNode* next = cur->_pnext;
        free(cur);
        cur = next;
    }
    pst->_size = 0;
    pst->_phead = pst->_ptail = NULL;
}

typedef struct {
    Queue p1;
    Queue p2;
} MyStack;

MyStack* myStackCreate() {
    MyStack* st = (MyStack*)malloc(sizeof(MyStack));
    QueueInit(&(st->p1));
    QueueInit(&(st->p2));
    return st;
}

void myStackPush(MyStack* obj, int x) {
    if (!QueueEmpty(&(obj->p1))) {
        QueuePush(&(obj->p1), x);
    } else {
        QueuePush(&(obj->p2), x);
    }
}

int myStackPop(MyStack* obj) {
    Queue* empty = &(obj->p1);
    Queue* nonempty = &(obj->p2);
    if (!QueueEmpty(empty)) {
        empty = &(obj->p2);
        nonempty = &(obj->p1);
    }
    while (QueueSize(nonempty) > 1) {
        QueuePush(empty, QueueFront(nonempty));
        QueuePop(nonempty);
    }
    int ret = QueueFront(nonempty);
    QueuePop(nonempty);
    return ret;
}

int myStackTop(MyStack* obj) {
    if (!QueueEmpty(&obj->p1)) {
        return QueueBack(&(obj->p1));
    } else {
        return QueueBack(&(obj->p2));
    }
}
bool myStackEmpty(MyStack* obj) {
    return QueueEmpty(&(obj->p1)) && QueueEmpty(&(obj->p2));
}

void myStackFree(MyStack* obj) {
    QueueDestroy(&(obj->p1));
    QueueDestroy(&(obj->p2));
    free(obj);
}

各位看官姥爷点个赞再走吧,欢迎在评论区讨论。

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

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

相关文章

报错:(idea端口被占用)Web server failed to start. Port 9090 was already in use.

cmd里面输入&#xff1a; netstat -ano|findstr "9090" 可以看到pid是9644 然后再打开任务管理器

Redis实战—验证码登录注册

目录 基于Session Controller层 Service层 ServiceImpl层 ​编辑校验登录状态 ThreadLocal 登录拦截器 添加拦截器到Config Controller层实现 基于Redis ServiceImpl 新增刷新拦截器 添加拦截器到Config 基于Session Controller层 /*** 发送手机验证码*/PostMappi…

Docker三剑客从0到1

一、docker三剑客介绍 使用"三剑客"可以帮助我们解决docker host维护,多容器编排部署,多个docker host集群的各个难题。 docker-machine 创建虚拟机 我们知道docker使用了linux的内核技术(namespace 资源隔离,cgroup资源限制等),那么如果我想在windows或Mac系统上…

浅析扩散模型与图像生成【应用篇】(二十五)——Plug-and-Play

25. Plug-and-Play: Diffusion Features for Text-Driven Image-to-Image Translation 该文提出一种文本驱动的图像转换方法&#xff0c;输入一张图像和一个目标文本描述&#xff0c;按照文本描述对输入图像进行转换&#xff0c;得到目标图像。图像转换任务其实本质上属于图像编…

【Flask框架】

6.Flask轻量型框架 6.1Flask简介 python提供的框架中已经写好了一个内置的服务器&#xff0c;服务器中的回应response行和头已经写好&#xff0c;我们只需要自己写显示在客户端&#xff0c;的主体body部分。 ---------------------------------------------------------- Fla…

【Linux】常用指令、热键与权限管理

一、常用指令 &#xff08;1&#xff09;ls 功能&#xff1a;列出指定目录下的所有子目录与文件 用法&#xff1a;ls &#xff08;选项&#xff09; &#xff08;目录或文件名&#xff09; 常用选项&#xff1a; -a&#xff1a;列出目录下的所有文件&#xff0c;包括隐藏…

k8s环境部署的集成arthas-spring-boot-starter spingboot项目无法访问控制台

前言 k8s环境部署的集成arthas-spring-boot-starter项目无法访问控制台&#xff0c;springboot项目集成arthas-spring-boot-starter 会自带个控制台 供我们访问 但是当使用k8s环境部署后 这个页面就无法访问了 分析 首先看下arthas对应的配置 arthas-spring-boot-starter 中…

linux基础指令讲解(ls、pwd、cd、touch、mkdir)

&#x1fa90;&#x1fa90;&#x1fa90;欢迎来到程序员餐厅&#x1f4ab;&#x1f4ab;&#x1f4ab; 主厨&#xff1a;邪王真眼 主厨的主页&#xff1a;Chef‘s blog 所属专栏&#xff1a;c大冒险 总有光环在陨落&#xff0c;总有新星在闪烁 这个是我们今天要用到的初始…

超实用的excel进销存管理系统(75份),自带库存预警,直接用!

进销存&#xff08;Inventory Management&#xff09;是企业管理中的一个核心组成部分&#xff0c;它涉及到商品的采购&#xff08;进货&#xff09;、销售和存储&#xff08;库存&#xff09;等环节。有效的进销存管理可以帮助企业降低成本、提高效率和客户满意度。 1. 采购管…

【上海大学计算机组成原理实验报告】五、机器语言程序实验

一、实验目的 理解计算机执行程序的实际过程。 学习编制机器语言简单程序的方法。 二、实验原理 根据实验指导书的相关内容&#xff0c;指令的形式化表示是指采用一种规范化的符号系统&#xff0c;以更清晰、精确地描述和表示指令的逻辑功能和操作步骤。 汇编是一种编程语言…

C++ 中重写重载和隐藏的区别

重写&#xff08;override&#xff09;、重载&#xff08;overload&#xff09;和隐藏&#xff08;overwrite&#xff09;在C中是3个完全不同的概念。我们这里对其进行详细的说明 1、重写&#xff08;override&#xff09;是指派生类覆盖了基类的虚函数&#xff0c;这里的覆盖必…

gitlab webhook触发jenkins任务

配置jenkins 安装gitlab插件 配置jenkins job 选择gitlab webhook触发 在高级中生成token 代码仓设置 新增webhook 配置webhook 测试连接 缺点&#xff0c;不能带gitLab事件的参数&#xff01;&#xff01;&#xff01;

Xilinx RAM IP核的使用及注意事项

对于RAM IP核(Block Memory Generator核)的使用以及界面的配置介绍&#xff0c;文章RAM的使用介绍进行了较详细的说明&#xff0c;本文对RAM IP核使用中一些注意的地方加以说明。 文章目录 三种RAM的区别单端口RAM(Single-port RAM)简单双端口RAM(Simple Dual-port RAM)真双端…

Spring Security入门教程:实现自定义用户配置

在上一篇文章中&#xff1a;Spring Security入门教程&#xff1a;利用Spring Security实现安全控制 我们学会了使用Spring Security实现安全控制&#xff0c;学会了他的基础使用&#xff0c;这节课我们来学习一下它的自定义的功能&#xff0c;更深入的了解和使用Spring Securit…

计算机组成结构—寻址方法

目录 一、指令寻址 二、数据寻址 1.立即寻址 2.直接寻址 3.间接寻址 4.隐含寻址 5.寄存器寻址 6.寄存器间接寻址 7.基址寻址 8.变址寻址 9.相对寻址 10. 堆栈寻址 寻址方式是寻找指令或操作数有效地址的方式&#xff0c;也就是指确定本条指令的数据地址&#xff0c;…

C++错题集(持续更新ing)

Day 1 一、选择题 解析&#xff1a; 在数字不会溢出的前提下&#xff0c;对于正数和负数&#xff0c;有&#xff1a; 1&#xff09;左移n位&#xff0c;相当于操作数乘以2的n次方&#xff1b; 2&#xff09;右移n位&#xff0c;相当于操作数除以2的n次方。 解析&#xff1a…

深度盘点在当今经济形势下资深项目经理或PMO的或去或从

在当今经济形势下&#xff0c;资深项目经理&#xff08;Project Manager&#xff09;或项目管理办公室&#xff08;PMO&#xff09;的去向和选择受到多种因素的影响。以下是对他们可能面临的或去或从的深度盘点&#xff1a; 1、发展去向 1. 深化专业领域&#xff1a;在经济形势…

2024年【制冷与空调设备运行操作】考试内容及制冷与空调设备运行操作考试试题

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 制冷与空调设备运行操作考试内容是安全生产模拟考试一点通生成的&#xff0c;制冷与空调设备运行操作证模拟考试题库是根据制冷与空调设备运行操作最新版教材汇编出制冷与空调设备运行操作仿真模拟考试。2024年【制冷…

如何实现Linux双网卡同时连接内网和外网的配置?

博主猫头虎的技术世界 &#x1f31f; 欢迎来到猫头虎的博客 — 探索技术的无限可能&#xff01; 专栏链接&#xff1a; &#x1f517; 精选专栏&#xff1a; 《面试题大全》 — 面试准备的宝典&#xff01;《IDEA开发秘籍》 — 提升你的IDEA技能&#xff01;《100天精通鸿蒙》 …