【数据结构实战篇】用C语言实现你的私有队列

news2024/11/27 5:12:00

🏝️专栏:【数据结构实战篇】

🌅主页:f狐o狸x


         在前面的文章中我们用C语言实现了栈的数据结构,本期内容我们将实现队列的数据结构

一、队列的概念

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

        入队列:进行插入操作的一端称为队尾

        出队列:进行删除操作的一端称为队头

二、队列的实现

        2.1 队列的定义

        动用你聪明的小脑袋想一想队列的结构是啥样的,是不是从队尾插入数据,再从队头输出数据,那是不是在队列的结构里面需要一个头结点,还需要一个尾节点,为了方便后面的操作,我们再加一个size变量来记录当前队列的大小


typedef int QDatatype;

typedef struct QueueNode
{
	QDatatype Data;
	struct QueueNode* next;
}QueueNode;

typedef struct Queue
{
	struct QueueNode* head;
	struct QueueNode* tail;
	int size;
}Queue;

        2.2 队列的初始化

//初始化队列
void QueueInit(Queue* pq)
{
	pq->size = 0;
	pq->head = NULL;
	pq->tail = NULL;
}

        2.3 队列入、出

        其实这里就是简单的尾插和头删

//队列增
void QueuePush(Queue* pq, QDatatype x)
{
	QueueNode* newnode = (QueueNode*)malloc(sizeof(QueueNode));
	if (newnode == NULL)
	{
		perror("malloc fail");
		return;
	}
	newnode->Data = x;
	newnode->next = NULL;

	if (pq->head == NULL)
	{
		assert(pq->tail == NULL);

		pq->head = pq->tail = newnode;
	}
	else
	{
		pq->tail->next = newnode;
		pq->tail = newnode;
	}

	pq->size++;
}
//队列删
void QueuePop(Queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(pq));
	QueueNode* cur = pq->head;
	if (cur->next == NULL)
	{
		free(cur);
		cur = NULL;
	}
	else
	{
		pq->head = pq->head->next;
		free(cur);
		cur = NULL;
	}
	pq->size--;
}

        2.4 检查队列是否为空、队列大小

//队列大小
int QueueSize(Queue* pq)
{
	assert(pq);
	return pq->size;
}
//判断队列是否为空
bool QueueEmpty(Queue* pq)
{
	assert(pq);
	return pq->size == 0;
}

        2.5 返回队头、队尾

//返回队头
QDatatype QueueFront(Queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(pq));
	return pq->head->Data;
}
//返回队尾
QDatatype QueueBack(Queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(pq));
	return pq->tail->Data;
}

        2.6 测试队列


int main()
{
	Queue Q = { 0 };
	QueueInit(&Q);
	QueuePush(&Q, 1);
	QueuePush(&Q, 2);
	QueuePush(&Q, 3);
	QueuePush(&Q, 4);
	QueuePush(&Q, 5);
	QueuePush(&Q, 6);

	while (!QueueEmpty(&Q))
	{
		printf("%d ", QueueFront(&Q));
		QueuePop(&Q);
	}


	return 0;
}

        运行结果如下:

三、实战练习

        学习了栈和队列的数据结构,我们现在就来练练手

        3.1 有效的括号

        力扣链接:有效的括号

        给定一个只包括 '('')''{''}''['']' 的字符串 s ,判断字符串是否有效

        3.1.1题目分析

        这个题可以用栈的结构来完成这个题,如果字符串中是左括号 ‘ ( ’ ‘ [ ’ ‘ { ’,则正常入栈,如果字符串为右括号‘ ) ’ ‘ ] ’ ‘ } ’,则将这个字符和栈顶元素对比,如果相等就进行下一次循环,如果没有匹配成功,则放回false,循环结束后,并且栈里没有元素了,就返回true,记得在每次返回的时候将空间释放了,不要有内存泄漏哈~

        3.1.2 解题代码

        对了,因为这里用的是c语言,因此我们需要自己手搓一个栈,不过问题不大啦

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>

typedef int StackDataType;

typedef struct stack
{
	int* StackData;
	int top;
	int capacity;
}ST;

//初始化
void InitStack(ST* ps);
//销毁
void DestoryStack(ST* ps);
//增加
void STPush(ST* ps, StackDataType x);
//删除
void STPop(ST* ps);
//判断是否为空
bool STEmpty(ST* ps);
//栈顶位置
StackDataType STTop(ST* ps);

//初始化
void InitStack(ST* ps)
{
	assert(ps);
	ps->StackData = (StackDataType*)malloc(sizeof(StackDataType)*4);
	if (ps->StackData == NULL)
	{
		perror("InitStack::malloc");
		return;
	}
	ps->capacity = 4;
	ps->top = 0;
}

//销毁
void DestoryStack(ST* ps)
{
	assert(ps);

	free(ps->StackData);
	ps->StackData = NULL;
	ps->capacity = 0;
	ps->top = 0;
}

//增加
void STPush(ST* ps, StackDataType x)
{
	assert(ps);

	if (ps->top == ps->capacity)
	{
		StackDataType* tmp = (StackDataType*)realloc(ps->StackData,
			sizeof(StackDataType) * ps->capacity * 2);
		if(tmp == NULL)
		{
			perror("STPush::realloc");
			return;
		}
		ps->StackData = tmp;
		ps->capacity *= 2;
	}
	
	ps->StackData[ps->top] = x;
	ps->top += 1;

}

//删除
void STPop(ST* ps)
{
	assert(ps);
	assert(!STEmpty(ps));

	ps->top--;
}

//判断是否为空
bool STEmpty(ST* ps)
{
	assert(ps);
	return ps->top == 0;
}

//栈顶位置
StackDataType STTop(ST* ps)
{
	assert(ps);
	assert(!STEmpty(ps));
	return ps->StackData[ps->top - 1];
}

bool isValid(char* s) {
    ST st = {0};
    InitStack(&st);
    char* ps = s;
    while(*s)
    {
        if(*s == '(' || *s == '[' || *s == '{')
        {
            STPush(&st, *s);//左括号入栈
        }
        else
        {
            if(STEmpty(&st))
            {
                DestoryStack(&st);
                return false;
            }
            char top = STTop(&st);
            STPop(&st);
            if((*s == ')' && top != '(') ||
                (*s == ']' && top != '[') ||
                (*s == '}' && top != '{'))
            {
                DestoryStack(&st);
                return false;                
            }
        }
        s++;
    }
    bool ret = STEmpty(&st);
    DestoryStack(&st);

    return ret;
}

        3.2 用队列实现栈

        力扣链接:用队列实现栈

        请你仅使用两个队列实现一个后入先出(LIFO)的栈,并支持普通栈的全部四种操作(pushtoppop 和 empty

        3.2.1 题目分析

        题目要求我们用两个队列来实现栈的结构,因此我们可以先随便将数据输入到一个队列中,再把队列一中的数据除了最后一个,全部转移到另外一个空的队列中,这样就可以实现栈的操作

         3.2.2 解题代码

        这里也是同样的需要我们手搓一个队列出来,不过上面已经实现过来,所以我们直接cv一下

typedef int QDatatype;

typedef struct QueueNode
{
	QDatatype Data;
	struct QueueNode* next;
}QueueNode;

typedef struct Queue
{
	struct QueueNode* head;
	struct QueueNode* tail;
	int size;
}Queue;

//初始化队列
void QueueInit(Queue* pq);
//销毁队列
void QueueDestroy(Queue* pq);
//队列增
void QueuePush(Queue* pq, QDatatype x);
//队列删
void QueuePop(Queue* pq);
//队列大小
int QueueSize(Queue* pq);
//判断队列是否为空
bool QueueEmpty(Queue* pq);
//返回队头
QDatatype QueueFront(Queue* pq);
//返回队尾
QDatatype QueueBack(Queue* pq);

//初始化队列
void QueueInit(Queue* pq)
{
	pq->size = 0;
	pq->head = NULL;
	pq->tail = NULL;
}

//销毁队列
void QueueDestroy(Queue* pq)
{
	assert(pq);
	QueueNode* cur = pq->head;
	while (cur)
	{
		QueueNode* del = cur;
        cur = cur->next;
		free(del);
	}
	pq->head = NULL;
	pq->tail = NULL;
	pq->size = 0;
}
//队列增
void QueuePush(Queue* pq, QDatatype x)
{
	QueueNode* newnode = (QueueNode*)malloc(sizeof(QueueNode));
	if (newnode == NULL)
	{
		perror("malloc fail");
		return;
	}
	newnode->Data = x;
	newnode->next = NULL;

	if (pq->head == NULL)
	{
		assert(pq->tail == NULL);

		pq->head = pq->tail = newnode;
	}
	else
	{
		pq->tail->next = newnode;
		pq->tail = newnode;
	}

	pq->size++;
}
//队列删
void QueuePop(Queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(pq));
	if (pq->head->next == NULL)
	{
		free(pq->head);
		pq->head = NULL;
	}
	else
	{
	    QueueNode* next = pq->head->next;
		free(pq->head);
		pq->head = next;
	}

	pq->size--;
}
//队列大小
int QueueSize(Queue* pq)
{
	assert(pq);
	return pq->size;
}
//判断队列是否为空
bool QueueEmpty(Queue* pq)
{
	assert(pq);
	return pq->size == 0;
}
//返回队头
QDatatype QueueFront(Queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(pq));
	return pq->head->Data;
}
//返回队尾
QDatatype QueueBack(Queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(pq));
	return pq->tail->Data;
}


typedef struct {
    Queue q1;
    Queue q2;
} MyStack;


MyStack* myStackCreate() {
    MyStack* pst = (MyStack*)malloc(sizeof(MyStack));
    if(pst == NULL)
    {
        perror("myStackCreate::malloc");
    }
    QueueInit(&pst->q1);
    QueueInit(&pst->q2);
    return pst;
}

void myStackPush(MyStack* obj, int x) {

    if(!QueueEmpty(&obj->q1))
    {
        QueuePush(&obj->q1,x);
    }
    else
    {
        QueuePush(&obj->q2,x);
    }
}

int myStackPop(MyStack* obj) {
    Queue* emptyQ = &obj->q1;
    Queue* nonemptyQ = &obj->q2;
    if(!QueueEmpty(&obj->q1))
    {
        emptyQ = &obj->q2;
        nonemptyQ = &obj->q1;
    }
    while(QueueSize(nonemptyQ)>1)
    {
        QueuePush(emptyQ,QueueFront(nonemptyQ));
        QueuePop(nonemptyQ);
    }
    int top = QueueFront(nonemptyQ);
    QueuePop(nonemptyQ);
    return top;
}

int myStackTop(MyStack* obj) {
    if(!QueueEmpty(&obj->q1))
    {
        return QueueBack(&obj->q1);
    }
    else
    {
        return QueueBack(&obj->q2);

    }

}

bool myStackEmpty(MyStack* obj) {
    return QueueEmpty(&obj->q1) && QueueEmpty(&obj->q2);
}

void myStackFree(MyStack* obj) {
    QueueDestroy(&obj->q1);
    QueueDestroy(&obj->q2);

    free(obj);
}

        本期内容到这里就完啦,感谢大家观看~

        对了对了,留下你的三连吧,求你啦~ QAQ

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

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

相关文章

实战项目负载均衡式在线 OJ

> 作者&#xff1a;დ旧言~ > 座右铭&#xff1a;松树千年终是朽&#xff0c;槿花一日自为荣。 > 目标&#xff1a;能自己实现负载均衡式在线 OJ。 > 毒鸡汤&#xff1a;有些事情&#xff0c;总是不明白&#xff0c;所以我不会坚持。早安! > 专栏选自&#xff1…

银河麒麟桌面系统——桌面鼠标变成x,窗口无关闭按钮的解决办法

银河麒麟桌面系统——桌面鼠标变成x&#xff0c;窗口无关闭按钮的解决办法 1、支持环境2、详细操作说明步骤1&#xff1a;用root账户登录电脑步骤2&#xff1a;导航到kylin-wm-chooser目录步骤3&#xff1a;编辑default.conf文件步骤4&#xff1a;重启电脑 3、结语 &#x1f49…

数据结构--AVL树(平衡二叉树)

✅博客主页:爆打维c-CSDN博客​​​​​​ &#x1f43e; &#x1f539;分享c、c知识及代码 &#x1f43e; &#x1f539;Gitee代码仓库 五彩斑斓黑1 (colorful-black-1) - Gitee.com 一、AVL树是什么&#xff1f;&#xff08;含义、性质&#xff09; 1.AVL树的概念 AVL树是最…

【Unity How】如何让物体跟随平台移动或旋转?

先看下最终要实现的效果&#xff1a; 当查找这个问题的资料时&#xff0c;发现多数的方案都是将物体设置为平台的子对象。 但是如果平台是非均匀缩放时&#xff0c;物体在移动或旋转时就会发生变形。 参考&#xff1a;Unity中父对象是非均匀缩放时出现倾斜或剪切现象 那有没有…

C语言函数递归经典题型——汉诺塔问题

一.汉诺塔问题介绍 Hanoi&#xff08;汉诺&#xff09;塔问题。古代有一个梵塔&#xff0c;塔内有3个座A、B、C&#xff0c;开始时&#xff21;座上有64个盘子&#xff0c;盘子大小不等&#xff0c;大的在下&#xff0c;小的在上。有一个老和尚想把这64个盘子从&#xff21;座移…

Unity中动态生成贴图并保存成png图片实现

实现原理&#xff1a; 要生成长x宽y的贴图&#xff0c;就是生成x*y个像素填充到贴图中&#xff0c;如下图&#xff1a; 如果要改变局部颜色&#xff0c;就是从x1到x2(x1<x2),y1到y2(y1<y2)这个范围做处理&#xff0c; 或者要想做圆形就是计算距某个点&#xff08;x1,y1&…

vue3封装Element Plus table表格组件

支持绝大部分Element Plus原有设置属性&#xff0c;支持分页&#xff0c;支持动态适配高度 效果展示 组件代码&#xff1a; <template><div class"table-wrap" ref"tableWrap"><el-tableclass"w100 h100":data"tableInfo.…

ElasticSearch学习篇18_《检索技术核心20讲》LevelDB设计思想

目录 一些常见的设计思想以及基于LSM树的LevelDB是如何利用这些设计思想优化存储、检索效率的。 几种常见的设计思想 索引和数据分离减少磁盘IO读写分离分层思想 LevelDB的设计思想 读写分离设计分层设计与延迟合并LRU缓存加速检索 几种常见设计思想 索引与数据分离 索引…

路由器中继与桥接

一 . 背景 现在的路由器大多数已经开始支持多种网络连接模式&#xff0c;以下将以TP-Link迷你无线路由器为例进行展开介绍。在TP-Link迷你无线路由器上一般有AP&#xff08;接入点&#xff09;模式&#xff0c;Router&#xff08;无线路由&#xff09;模式&#xff0c;Repeate…

Bitcoin---P2SH;P2SH举例;P2SH的局限性

文章目录 1. 摘要2. P2SH举例3. P2SH局限性 1. 摘要 Pay-to-Script-Hash (P2SH) 交易输出的开发是为了简化更复杂和功能性脚本的使用&#xff0c;就像需要提供相应签名才能解锁的支付脚本&#xff08;即 P2PKH 脚本&#xff09;一样简单。为了轻松使用此类兑换脚本&#xff0c…

鸿蒙NEXT开发案例:文字转拼音

【引言】 在鸿蒙NEXT开发中&#xff0c;文字转拼音是一个常见的需求&#xff0c;本文将介绍如何利用鸿蒙系统和pinyin-pro库实现文字转拼音的功能。 【环境准备】 • 操作系统&#xff1a;Windows 10 • 开发工具&#xff1a;DevEco Studio NEXT Beta1 Build Version: 5.0.…

ffmpeg视频滤镜:提取缩略图-framestep

滤镜描述 官网地址 > FFmpeg Filters Documentation 这个滤镜会间隔N帧抽取一帧图片&#xff0c;因此这个可以用于设置视频的缩略图。总体上这个滤镜比较简单。 滤镜使用 滤镜参数 framestep AVOptions:step <int> ..FV....... set frame st…

eclipse-git项目提示NO-HEAD

1、出现该问题的过程 本人在用eclipse拉取git代码&#xff0c;刚拉取完&#xff0c;可能还没来得及跟本地的分支合并&#xff0c;电脑就卡动了。无奈只能重启电脑&#xff0c;打开eclipse&#xff0c;maven项目后面就出现了xxx NO-HEAD的提示。 2、问题解决 根据错误提示&am…

力扣hot100-->排序

排序 1. 56. 合并区间 中等 以数组 intervals 表示若干个区间的集合&#xff0c;其中单个区间为 intervals[i] [starti, endi] 。请你合并所有重叠的区间&#xff0c;并返回 一个不重叠的区间数组&#xff0c;该数组需恰好覆盖输入中的所有区间 。 示例 1&#xff1a; 输…

鱼眼相机模型-MEI

参考文献&#xff1a; Single View Point Omnidirectional Camera Calibration from Planar Grids 1. 相机模型如下&#xff1a; // 相机坐标系下的点投影到畸变图像// 输入&#xff1a;相机坐标系点坐标cam 输出&#xff1a; 畸变图像素点坐标disPtvoid FisheyeCamAdapter::…

Reactor 模式的理论与实践

1. 引言 1.1 什么是 Reactor 模式&#xff1f; Reactor 模式是一种用于处理高性能 I/O 的设计模式&#xff0c;专注于通过非阻塞 I/O 和事件驱动机制实现高并发性能。它的核心思想是将 I/O 操作的事件分离出来&#xff0c;通过事件分发器&#xff08;Reactor&#xff09;将事…

windows下安装wsl的ubuntu,同时配置深度学习环境

写在前面&#xff0c;本次文章只是个人学习记录&#xff0c;不具备教程的作用。个别信息是网上的&#xff0c;我会标注&#xff0c;个人是gpt生成的 安装wsl 直接看这个就行&#xff1b;可以不用备份软件源。 https://blog.csdn.net/weixin_44301630/article/details/1223900…

深入探索 CnosDB 可观测性最佳实践:开篇

随着云计算、微服务、容器化和 DevOps 等技术的迅猛发展&#xff0c;现代软件系统变得愈加复杂和动态。传统的监控手段已经无法满足对系统状态的全面、实时、准确地了解。在这样的背景下&#xff0c;可观测性&#xff08;Observability&#xff09;作为一种新兴的技术理念应运而…

World of Warcraft /script SetRaidTarget(“target“, n, ““) n=8,7,6,5,4,3,2,1,0

魔兽世界执行当前目标标记方法 /script SetRaidTarget("target", n, "") n8,7,6,5,4,3,2,1,0 解析这个lua脚本 D:\Battle.net\World of Warcraft\_classic_\Interface\AddOns\wMarker wMarker.lua /script SetRaidTarget("target", 8, &quo…

[极客大挑战 2019]BabySQL--详细解析

信息搜集 进入界面&#xff1a; 输入用户名为admin&#xff0c;密码随便输一个&#xff1a; 发现是GET传参&#xff0c;有username和password两个传参点。 我们测试一下password点位能不能注入&#xff1a; 单引号闭合报错&#xff0c;根据报错信息&#xff0c;我们可以判断…