栈和队列--数据结构初阶(2)(C/C++)

news2025/4/22 5:41:21

文章目录

  • 前言
  • 理论部分
    • 栈的模拟实现
    • STL中的栈容器
    • 队列的模拟实现
    • STL中的队列容器
  • 作业部分

前言

这期的话会给大家讲解栈和队列的模拟实现和在STL中栈和队列怎么用的一些知识和习题部分(这部分侧重于理论知识,习题倒还是不难)

理论部分

栈的模拟实现


typedef int  STDataType;

typedef struct Stack
{
	STDataType* a;//这里的a想表示的是数组
	int top;//表示数组a当前的容量
	int capacity;
}ST;

void STInit(ST* ps)
{
	assert(ps);

	ps->a = (STDataType*)malloc(sizeof(STDataType) * 4);
	if (ps->a == NULL)
	{
		perror("malloc fail");
		return;
	}

	ps->capacity = 4;
	ps->top = 0;  
}

void STDestroy(ST* ps)
{
	assert(ps);

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

void STPush(ST* ps, STDataType x)
{
	assert(ps);

	if (ps->top == ps->capacity)
	{
		STDataType* tmp = (STDataType*)realloc(ps->a,sizeof(STDataType) * ps->capacity*2);
		if (tmp == NULL)
		{
			perror("realloc fail");
			return;
		}

		ps->a = tmp;
		ps->capacity *= 2;
	}

	ps->a[ps->top] = x;
	ps->top++;
}

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

	ps->top--;
}

int STSize(ST* ps)
{
	assert(ps);

	return ps->top;
}

bool STEmpty(ST* ps)
{
	assert(ps);

	return ps->top == 0;
}//拓展:bool里面如果return的是数字的话,会隐式转换

STDataType STTop(ST* ps)
{
	assert(ps);
	assert(!STEmpty(ps));

	return ps->a[ps->top - 1];
}
注意:这样写的话,此时的栈顶的下标是top-1
stPush那里一般用ps->top == ps->capacity
top那里是还没存元素的
开空间完记得检查是否开辟成功
尽量不要用while(st.top!=0去代替while(!STEmpty(&st))),数据结构最好封装起来
注意STTop最后那里是ps->a[ps->top-1]
这个代码有个问题:封装时一般要typedef类型,这里搞了但是没去用
               (让以后要改类型时只用改一次)

STL中的栈容器

stack容器(栈)
头文件:#include<stack>
创建:stack<T>st;//st是变量名,可以改;T是任意类型的数据
size empty 
push:进栈
pop:出栈
top:返回栈顶元素,但是不会删除栈顶元素

(先进后出)

队列的模拟实现

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

typedef char QDatatype;

typedef struct QueueNode
{
	struct QueueNode* next;
	QDatatype data;
}QNode;

typedef struct Queue
{
	QNode* head;
	QNode* 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)
{
	assert(pq);

	pq->head = pq->tail = NULL;
	pq->size = 0;
}

void QueueDestroy(Queue* pq)
{
	assert(pq);
	QNode* cur = pq->head;
	while (cur)
	{
		QNode* next = cur->next;
		free(cur);
		cur = next;
	}

	pq->head = pq->tail = NULL;
	pq->size = 0;
}

void QueuePush(Queue* pq, QDatatype x)
{
	QNode* newnode = (QNode*)malloc(sizeof(QNode));
	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(pq->head != NULL);

	if (pq->head->next == NULL)
	{
		free(pq->head);
		pq->head = pq->tail = NULL;
	}
	else
	{
		QNode* 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;
}
结构体定义那里可以像这样在结构体里面用自己的指针
结构体1里面套结构体2的话,定义结构体1后不用单独手动再为结构体1中的结构体2开辟
跟定义int指针,想变成数组需要malloc区分
注意:assert检查的是结果为0,就会报错

STL中的队列容器

queue(队列):
头文件:#include<queue>
创建:queue<T>q;//q是变量名,T是任意类型的数据
size empty push pop
front:返回队头元素,但不会删除
back:返回队尾元素,但不会删除
不可以用clear来直接清除队列

pop删除的是队头

作业部分

力扣 有效的括号

力扣 有效的括号
注意点:右括号数量不等于左括号这个特殊情况不要忘了
感悟:像这种如果匹配的话要继续走,不匹配的话要干啥的if里面写不匹配的条件会好些

代码实现:
typedef struct Stack
{
    char*a;
    int top;
    int capacity;

}
 void  STInit()
 {
    a = (char*)malloc(sizeof(char)*4);
    capacity = 4;
    top = 0;
 }
 void STPush(char*ps,char x)
 {
    assert(ps);
    if(ps->top == ps->capacity)
    {
        a = (char*)malloc(sizeof(char)*ps->capacity*2);
        capacity*=2;

    }
    ps->a[ps->top] = x;
    ps->top++;
 }
 void STPop(char*ps,char x)
 {
    assert(ps);
    ps->top--;
 }


bool isValid(char* s) {
    struct Stack;
    &a = &s;
    

}
if如果判断条件多的话可以像下面这样写,这样写不用续行符
而且if后面只跟一个语句的话,一般跟if写同一行上

在这里插入图片描述

企业中的话,能初始化的尽量还是要初始化一下,竞赛一般不用

力扣 用栈实现队列

题目: 力扣 用栈实现队列
相比用队列实现栈可以优化的地方是:可以有个栈专门入栈,一个栈专门出栈,出栈的空了再把另一个栈倒过来

代码实现:
class MyQueue {
public:
   
        stack<int>q1;
        stack<int>q2;
   int count1 = 0;
    //用q1来存入栈,q2来搞出栈
    void push(int x) {
       
       q1.push(x);
        
    }
    
    int pop() {
        if(!q2.empty())
        {
          int m =   q2.top();
        
            q2.pop();
            return m;
            
        }
        else{
            while(q1.size())
            {
                int k = q1.top();
                q2.push(k); q1.pop();
            }
            int n = q2.top();
            q2.pop();
            return n;
        }
    }
    
    int peek() {
        if(!q2.empty())
        {
            return q2.top();
        }
        else 
        {
             while(q1.size())
            {
                q2.push(q1.top()); q1.pop();
            }
            return q2.top();
        }
    }
    
    bool empty() {
        if(q1.empty()&&q2.empty())
        return true;
        else{
            return false;
        }
    }
};


力扣 设计循环队列

题目:力扣 设计循环队列
这里用链表模拟队列不好(因为要找尾)所以用数组来模拟
想让数组也能循环的话,就要时不时让他对k取模(插入,删除过程中也要)
由这个题引申出来的知识有:
1.malloc了几次,后续也要free几次,虽然说不free也可以通过,但是要是在面试中就是减分项,比如下面这种malloc的方式

在这里插入图片描述
在这里插入图片描述


代码实现:

typedef struct {
    int*a;
    int front;
    int rear;
    int k;

} MyCircularQueue;


MyCircularQueue* myCircularQueueCreate(int k) {
    MyCircularQueue*obj  = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));
    obj->front = obj->rear = 0;
    obj->k = k;
    obj->a = (int*)malloc(sizeof(int)*(k+1));
    return obj;
}
bool myCircularQueueIsEmpty(MyCircularQueue* obj) {
    return obj->front == obj->rear;
}

bool myCircularQueueIsFull(MyCircularQueue* obj) {
    return (obj->rear+1)%(obj->k+1) == obj->front;
    //这里的作用是让rear在数组末时可以返回到0那去以及防止是空
}

bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {
    if(myCircularQueueIsFull(obj))    return false;
    obj->a[obj->rear] = value;
    obj->rear = ((++obj->rear))%(obj->k+1);
    
    return true;
}

bool myCircularQueueDeQueue(MyCircularQueue* obj) {
    if(myCircularQueueIsEmpty(obj))  return false;
    obj->front = (++obj->front)%(obj->k+1);
    return true;
}

int myCircularQueueFront(MyCircularQueue* obj) {
    if(myCircularQueueIsEmpty(obj))
    {
        return -1;
    }
    return obj->a[obj->front];
}

int myCircularQueueRear(MyCircularQueue* obj) {
     if(myCircularQueueIsEmpty(obj))
    {
        return -1;
    }
    return obj->a[(obj->rear-1+obj->k+1)%(obj->k+1)];
}



void myCircularQueueFree(MyCircularQueue* obj) {
    free(obj->a);
    free(obj);
}


队列和栈都属于线性数据结构   循环队列也是线性数据结构

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

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

相关文章

C++常用函数合集

万能头文件&#xff1a;#include<bits/stdc.h> 1. 输入输出流&#xff08;I/O&#xff09;函数 1.1cin 用于从标准输入流读取数据。 1.2cout 用于向标准输出流写入数据。 // 输入输出流&#xff08;I/O&#xff09;函数 #include <iostream> using namespace…

OpenGL shader开发实战学习笔记:第十二章 深入光照

1. 深入光照 1.1. 平行光 我们在前面的章节中&#xff0c;已经介绍了平行光的基本原理和实现步骤 平行光的基本原理是&#xff0c;所有的光都从同一个方向照射到物体上&#xff0c;这个方向就是平行光的方向。 1.2. 点光源 点光源的基本原理是&#xff0c;所有的光都从一个…

PCB 射频天线设计和版图创建技巧

本文要点 射频天线有多种形式&#xff0c;从整合在芯片中的扁平天线&#xff0c;到直接印制在PCB上的铜质天线。 创建带有一个或多个天线的版图时&#xff0c;需要确保在PCB不同电路模块之间彼此隔离。 在设计一个射频天线时&#xff0c;应该使用CAD工具&#xff0c;此类…

uniapp-商城-29-vuex 关于系统状态的管理

按照我们前面讲的&#xff0c;vuex&#xff0c;的使用方式&#xff1a; 步骤如下&#xff1a; 1 先创建store 文件夹 2 在 store 中 创建一个 index.js 3、 在 store 中&#xff0c;创建一个modules文件夹 4、在store中&#xff0c;创建一个getters.js 5、在modules文件…

小迪安全-112-yii反序列化链,某达oa,某商场,影响分析

yii是和tp一样的框架 入口文件 web目录下 相对tp比较简单一些&#xff0c;对比tp找一下他的url结构 对应的位置结构 这个contorllers文件的actionindex就是触发的方法 控制器&#xff0c;指向的index文件&#xff0c;就可以去视图模块看index文件 这就是前端展示的文件 自…

区间选点详解

步骤 operator< 的作用在 C 中&#xff0c; operator< 是一个运算符重载函数&#xff0c;它定义了如何比较两个对象的大小。在 std::sort 函数中&#xff0c;它会用到这个比较函数来决定排序的顺序。 在 sort 中&#xff0c;默认会使用 < 运算符来比较两个对象…

如何在白平衡标定种构建不同类型的白平衡色温坐标系

目录 一、预备知识&#xff1a; 二、常见的白平衡色温坐标系 三、白平衡色温坐标系的理解 1&#xff09;横纵坐标轴分别代表什么含义&#xff1f; 2&#xff09;色温坐标系中原点表示什么含义&#xff1f; 3&#xff09;某M/某H的色温坐标为什么是长成这样呢&#xff1f;…

Oracle RMAN同步数据库Active database duplicate

Active database duplicate&#xff0c;不需要先把目标数据库进行rman备份&#xff0c;只要目标数据库处于归档模式下即可直接通过网络对数据库进行copy&#xff0c;且copy完成后自动open数据库。这对于大数据特别是T级别的数据库来说优点非常明显&#xff0c;复制前不需要进行…

基于DeepSeek/AI的资产测绘与威胁图谱构建

引言&#xff1a; 在网络安全攻防实践中&#xff0c;资产测绘是红队作战与蓝队安全运营的第一步&#xff0c;其本质都是通过系统性信息采集实现攻击面管理。 当前普遍存在的痛点在于&#xff0c;当企业级资产规模呈指数级增长时&#xff0c;传统基于规则引擎的低效批量处理方式…

构建自动翻译工作流:技术与实践

一、引言 制药行业客户迫切需要一种翻译解决方案&#xff0c;以解决公司内部多样化的翻译难题。他们需要的不仅是提升翻译效率和准确性的工具&#xff0c;更希望能够保持文档的原始格式。我们观察到客户的需求广泛&#xff0c;包括多语言办公文件、研究文档和药品报批文件等&a…

【Linux】中的网络管理

目录 1.ipv4原理&#xff0c;网关与DNS定义 2ip图形化配置--nm 2.1图形化平台配置 2.2无图形化平台配置 3.常用的网络命令--ping&#xff0c;wget&#xff0c;curl ping wget curl 4.ip命令临时配置---ifconfig&#xff0c;ip a ifconfig ip address 5.ip命令永久配…

elasticsearch中文分词器插件下载教程

一、下载原因&#xff1a; 我们的业务中通常使⽤的是中⽂分词&#xff0c;es的中⽂分词默认会将中⽂词每个字看成⼀个词⽐如&#xff1a;“我想吃⾁夹馍”会被分为”我”&#xff0c;”想”&#xff0c;”吃”&#xff0c;”⾁” &#xff0c;”夹”&#xff0c;”馍” 这显然是…

门面模式与适配器模式

一、门面模式 门面模式&#xff1a;提供统一接口访问子系统接口 1、包含角色 外观系统对外的统一接口子系统类的集合&#xff1b;并不知道外观角色的存在&#xff0c;需要为了配合外观角色而做特殊处理或修改 2、举例 原本开关灯要分别操作各个房间的灯&#xff0c;现在设置总…

QSS【QT】

文章目录 QSSid选择器 & 类型选择器伪类选择器盒子模型 QSS 设置样式的时候&#xff0c;是可以指定某个控件来设置的。 指定控件之后&#xff0c;此时的样式就会针对这个指定的控件&#xff0c;也会针对子控件生效 ui->pushButton_2->setStyleSheet("QPushButt…

css 中float属性及clear的释疑

float属性可以让元素脱离文档流&#xff0c;父元素中的子元素设置为float,则会导致父元素的高度塌陷。 <style type"text/css"> .father{ /*没有给父元素定义高度*/background:#ccc; border:1px dashed #999; } .box01,.box02,.box0…

BH1750光照传感器---附代码

目录 BH1750简介BH1750指令集BH1750工作流程 BH1750简介 VCC-->电源正&#xff1b; ADDR-->地址端口&#xff1b; GND-->电源负&#xff1b; PA5-->SDA-->I2C数据线&#xff1b; PA3-->SCL-->I2C时钟线&#xff1b; DVI-->I2C端口参考电压&#xff1b…

蔡浩宇的AIGC游戏革命:从《原神》到《Whispers》的技术跨越

目录 引言&#xff1a;游戏行业的AI革命前夜 一、《Whispers》的技术突破与市场挑战 1.1 多模态AI技术的集成应用 1.2 与传统游戏的差异化体验 1.3 面临的商业化难题 二、从《原神》到《Whispers》的技术演进 2.1 《原神》成功的时代因素分析 2.2 蔡浩宇的技术路线转变 …

前端vue+typeScritp+elementPlus基础页面实现:

效果&#xff1a; 前端代码&#xff1a; index.vue: <template><el-container><el-main><el-card class"search-card" shadow"never"><transition :enter-active-class"proxy?.animate.searchAnimate.enter" :le…

leetcode第20题(有效的括号)

思路解析&#xff08;使用栈&#xff09;&#xff1a; 使用一个栈来保存左括号。 每当遇到一个右括号时&#xff0c;检查栈顶元素是否是匹配的左括号。 如果匹配&#xff0c;则弹出栈顶元素&#xff1b; 如果不匹配或者栈为空&#xff0c;则说明无效&#xff1b; 最后如果栈…

超简单的git学习教程

本博客仅用于记录学习和使用 前提声明全部内容全部来自下面廖雪峰网站&#xff0c;如果侵权联系我删除 0.前言 相信有不少人被推荐那个游戏学习git&#xff0c;一个不止我一个完全没学习过的进去后一脸懵&#xff0c;半天都通不过一关然后就放弃了&#xff0c;我个人觉得那个…