初阶数据结构:栈与队列的扩展补充

news2024/12/23 18:51:12

目录

  • 1. 栈与队列练习题
    • 1.1 栈的括号匹配问题
    • 1.2 用队列来实现栈
    • 1.3 用栈来实现队列
    • 1.4 扩展:循环队列

1. 栈与队列练习题

1.1 栈的括号匹配问题

  1. 题目信息:
    在这里插入图片描述
  2. 题目链接:
    括号匹配问题

思路: 利用栈的后进先出特性来实现括号的匹配

  1. 当遇到 ‘(’,‘{’,‘[’,这三种括号时进行压栈
  2. 当遇到’)‘,’}‘,’]',这三种括号时将括号中的元素进行出栈匹配

过程演示:

在这里插入图片描述

typedef char STDataType;
typedef struct Stack
{
	STDataType* _a;
	int _top; // 栈顶
	int _capacity; // 容量
}Stack;

void CheckCapacity(Stack* ps)
{
	if (ps->_capacity == ps->_top)
	{
		int newcapacity = ps->_capacity == 0 ? 4 : 2 * ps->_capacity;
		STDataType* data = (STDataType*)realloc(ps->_a, newcapacity * sizeof(STDataType));
		if (data == NULL)
		{
			perror("realloc failed");
			exit(-1);
		}

		ps->_a = data;
		ps->_capacity = newcapacity;
	}
}


void StackInit(Stack* ps)
{
	ps->_capacity = 0;
	ps->_top = 0;
	ps->_a = NULL;

	CheckCapacity(ps);
}

void StackPush(Stack* ps, STDataType data)
{
	assert(ps);
	
	CheckCapacity(ps);
	ps->_a[ps->_top] = data;
	ps->_top++;
}

int StackEmpty(Stack* ps)
{
	assert(ps);

	return ps->_top == 0;
}

void StackPop(Stack* ps)
{
	assert(!StackEmpty(ps));

	ps->_top--;
}

STDataType StackTop(Stack* ps)
{
	assert(ps);
	assert(!StackEmpty(ps));

	return ps->_a[ps->_top - 1];
}

int StackSize(Stack* ps)
{
	assert(ps);

	return ps->_top;
}

void StackDestroy(Stack* ps)
{
	assert(ps);

	free(ps->_a);
	ps->_capacity = ps->_top = 0;
}

bool isValid(char* s) 
{
    Stack st1;
    StackInit(&st1);
    int i = 0;
    for(i = 0; s[i] != '\0'; i++)
    {
        if(s[i] == '(' || s[i] == '[' || s[i] == '{')
        {
            StackPush(&st1, s[i]);
        }
        else if(s[i] == ')' || s[i] == ']' || s[i] == '}')
        {
            if(StackEmpty(&st1))
            {
                return false;
            }
            
            char tmp = StackTop(&st1);
            if(s[i] == ')' && tmp == '(')
            {
                StackPop(&st1);
            }
            else if(s[i] == ']' && tmp == '[')
            {
                StackPop(&st1);
            }
            else if(s[i] == '}' && tmp == '{')
            {
                StackPop(&st1);
            }
            else
            {
                break;
            }
        }
    }

    if(StackEmpty(&st1))
    {
        return true;
    }

    return false;      
}

1.2 用队列来实现栈

  1. 题目信息:
    在这里插入图片描述
  2. 题目链接:
    用两个队列实现栈

在这里插入图片描述

myStack结构:
在这里插入图片描述

typedef int QDataType;

typedef struct QListNode
{
	struct QListNode* _pNext;
	QDataType _data;
}QNode;

typedef struct Queue
{
	QNode* _front;
	QNode* _rear;
}Queue;


void QueueInit(Queue* q)
{
	assert(q);

	q->_front = q->_rear = NULL;
}

QNode* BuyNewNode2(QDataType data)
{
	QNode* newnode = (QNode*)malloc(sizeof(QNode));
	if (newnode == NULL)
	{
		perror("malloc failed");
		exit(-1);
	}

	newnode->_data = data;
	newnode->_pNext = NULL;

	return newnode;
}

void QueuePush(Queue* q, QDataType data)
{
	assert(q);

	QNode* newnode = BuyNewNode2(data);
	if (q->_front == NULL)
	{
		q->_front = q->_rear = newnode;
	}
	else
	{
		q->_rear->_pNext = newnode;
		q->_rear = q->_rear->_pNext;
	}
}

int QueueEmpty(Queue* q)
{
	assert(q);

	return q->_front == NULL;
}

void QueuePop(Queue* q)
{
	assert(q);
	assert(!QueueEmpty(q));

	QNode* cur = q->_front->_pNext;
	free(q->_front);
	q->_front = cur;

	if (q->_front == NULL)
	{
		q->_rear = NULL;
	}
}

QDataType QueueFront(Queue* q)
{
	assert(q);
	assert(!QueueEmpty(q));

	return q->_front->_data;
}

QDataType QueueBack(Queue* q)
{
	assert(q);
	assert(!QueueEmpty(q));

	return q->_rear->_data;
}

int QueueSize(Queue* q)
{
	assert(q);

	int count = 0;
	QNode* cur = q->_front;
	while (cur)
	{
		cur = cur->_pNext;
		count++;
	}

	return count;
}

void QueueDestroy(Queue* q)
{
	assert(q);

	while (q->_front)
	{
		QueuePop(q);
	}
}

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

MyStack* myStackCreate()
{
	MyStack* obj = (MyStack*)malloc(sizeof(MyStack));
	QueueInit(&obj->q1);
	QueueInit(&obj->q2);

	return obj;
}

void myStackPush(MyStack* obj, int x)
{
	assert(obj);
	Queue* no_empty = &obj->q1;
	if (QueueEmpty(&obj->q1))
	{
		no_empty = &obj->q2;
	}

	QueuePush(no_empty, x);
}

bool myStackEmpty(MyStack* obj)
{
	assert(obj);

	return QueueEmpty(&obj->q1) && QueueEmpty(&obj->q2);
}

int myStackTop(MyStack* obj)
{
	assert(obj);
	assert(!myStackEmpty(obj));

	Queue* no_empty = &obj->q1;
	if (QueueEmpty(&obj->q1))
	{
		no_empty = &obj->q2;
	}

	return QueueBack(no_empty);
}

int myStackPop(MyStack* obj)
{
	Queue* no_empty = &obj->q1;
	Queue* empty = &obj->q2;
	if (QueueEmpty(&obj->q1))
	{
		no_empty = &obj->q2;
		empty = &obj->q1;
	}

	while (QueueSize(no_empty) > 1)
	{
		QueuePush(empty, QueueFront(no_empty));
		QueuePop(no_empty);
	}

	int val = QueueFront(no_empty);
	QueuePop(no_empty);

	return val;
}

void myStackFree(MyStack* obj)
{
	assert(obj);

	Queue* no_empty = &obj->q1;
	if (QueueEmpty(&obj->q1))
	{
		no_empty = &obj->q2;
	}

	QueueDestroy(no_empty);
	free(obj);
}

1.3 用栈来实现队列

  1. 题目信息:
    在这里插入图片描述
  2. 题目链接:
    用栈实现队列

过程演示:
在这里插入图片描述

typedef char STDataType;
typedef struct Stack
{
	STDataType* _a;
	int _top; // 栈顶
	int _capacity; // 容量
}Stack;

void CheckCapacity(Stack* ps)
{
	if (ps->_capacity == ps->_top)
	{
		int newcapacity = ps->_capacity == 0 ? 4 : 2 * ps->_capacity;
		STDataType* data = (STDataType*)realloc(ps->_a, newcapacity * sizeof(STDataType));
		if (data == NULL)
		{
			perror("realloc failed");
			exit(-1);
		}

		ps->_a = data;
		ps->_capacity = newcapacity;
	}
}


void StackInit(Stack* ps)
{
	ps->_capacity = 0;
	ps->_top = 0;
	ps->_a = NULL;

	CheckCapacity(ps);
}

void StackPush(Stack* ps, STDataType data)
{
	assert(ps);
	
	CheckCapacity(ps);
	ps->_a[ps->_top] = data;
	ps->_top++;
}

int StackEmpty(Stack* ps)
{
	assert(ps);

	return ps->_top == 0;
}

void StackPop(Stack* ps)
{
	assert(!StackEmpty(ps));

	ps->_top--;
}

STDataType StackTop(Stack* ps)
{
	assert(ps);
	assert(!StackEmpty(ps));

	return ps->_a[ps->_top - 1];
}

int StackSize(Stack* ps)
{
	assert(ps);

	return ps->_top;
}

void StackDestroy(Stack* ps)
{
	assert(ps);

	free(ps->_a);
	ps->_capacity = ps->_top = 0;
}

typedef struct 
{
    Stack push_stack;
    Stack pop_stack;    
} MyQueue;


MyQueue* myQueueCreate() 
{
    MyQueue* obj = (MyQueue*)malloc(sizeof(MyQueue));
    StackInit(&obj->push_stack);
    StackInit(&obj->pop_stack);

    return obj;    
}

void myQueuePush(MyQueue* obj, int x) 
{
    assert(obj);

    StackPush(&obj->push_stack, x);    
}

bool myQueueEmpty(MyQueue* obj) 
{
    assert(obj);

    return StackEmpty(&obj->push_stack) && StackEmpty(&obj->pop_stack);
}

int myQueuePeek(MyQueue* obj) 
{
    assert(obj);
    assert(!myQueueEmpty(obj));

    if(StackEmpty(&obj->pop_stack))
    {
        while(!StackEmpty(&obj->push_stack))
        {
            StackPush(&obj->pop_stack, StackTop(&obj->push_stack));
            StackPop(&obj->push_stack);
        }
    }

    return StackTop(&obj->pop_stack);
}

int myQueuePop(MyQueue* obj) 
{
    assert(obj);
    assert(!myQueueEmpty(obj));

    int data = myQueuePeek(obj);

    StackPop(&obj->pop_stack);

    return data;
}

void myQueueFree(MyQueue* obj) 
{
    assert(obj);

    StackDestroy(&obj->push_stack);
    StackDestroy(&obj->pop_stack);
    free(obj);    
}

1.4 扩展:循环队列

  1. 题目信息:
    在这里插入图片描述
  2. 题目链接:
    循环链表

过程演示:
在这里插入图片描述

typedef struct
{
	int* data;
	int c_front;
	int c_rear;
	int capacity_k;
} MyCircularQueue;


MyCircularQueue* myCircularQueueCreate(int k)
{
	MyCircularQueue* obj = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));
	//k + 1为构建循环链表所需的空间大小
	obj->data = (int*)malloc((k + 1) * sizeof(int));
	//注:k为能够存储的元素个数,即链表存储数据的容量
	obj->capacity_k = k;
	obj->c_front = obj->c_rear = 0;

	return obj;
}

bool myCircularQueueIsFull(MyCircularQueue* obj)
{
	assert(obj);

	int k = obj->capacity_k;

	return obj->c_front % (k + 1) == (obj->c_rear + 1) % (k + 1);
}

bool myCircularQueueEnQueue(MyCircularQueue* obj, int value)
{
	assert(obj);

	int k = obj->capacity_k;

	if (!myCircularQueueIsFull(obj))
	{
		int rear = obj->c_rear % (k + 1);
		obj->data[rear] = value;
		obj->c_rear++;

		return true;
	}

	return false;
}

bool myCircularQueueIsEmpty(MyCircularQueue* obj)
{
	assert(obj);

	int k = obj->capacity_k;

	return obj->c_front % (k + 1) == obj->c_rear % (k + 1);
}

bool myCircularQueueDeQueue(MyCircularQueue* obj)
{
	assert(obj);

	if (!myCircularQueueIsEmpty(obj))
	{
		obj->c_front++;

		return true;
	}

	return false;
}

int myCircularQueueFront(MyCircularQueue* obj)
{
	assert(obj);

	int k = obj->capacity_k;

	if (!myCircularQueueIsEmpty(obj))
	{
		int front = obj->c_front % (k + 1);

		return obj->data[front];
	}

	return -1;
}

int myCircularQueueRear(MyCircularQueue* obj)
{
	assert(obj);

	int k = obj->capacity_k;

	if (!myCircularQueueIsEmpty(obj))
	{
		int pre_rear = (obj->c_rear - 1) % (k + 1);

		return obj->data[pre_rear];
	}

	return -1;
}

void myCircularQueueFree(MyCircularQueue* obj)
{
	assert(obj);

	free(obj->data);
	free(obj);
}

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

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

相关文章

opencascade c#例程解析

1.编译 将msvc.bat文件拖入vs2022的x64 native tools&#xff0c;即可 2.about.xaml <Windowxmlns"http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x"http://schemas.microsoft.com/winfx/2006/xaml"x:Class"IE_WPF_WinForms…

吴恩达机器学习笔记十四 多输出的分类 多类和多标签的区别 梯度下降优化 卷积层

这里老师想讲的是multiclass classification和multilable classification的区别&#xff0c;下面是我从其他地方找到的说法: Multiclass classification 多类分类 意味着一个分类任务需要对多于两个类的数据进行分类。比如&#xff0c;对一系列的橘子&#xff0c;苹果或者梨的…

QT之液晶电子时钟

根据qt的<QLDNumber>做了一个qt液晶电子时钟. 结果 实时显示当前时间,左键可以拖动时钟在屏幕的位置,右键点击关闭显示. 实现过程 新建一个class文件,让这个文件的父类是QLCDNumber 相关功能变量定义和函数实现 .c文件代码 这里需要注意的一点是event->button是获取的…

langchain学习笔记(七)

RunnablePassthrough: Passing data through | &#x1f99c;️&#x1f517; Langchain 1、RunnablePassthrough可以在不改变或添加额外键的情况下传递输入。通常和RunnableParallel结合使用去分配数值给到字典的新键 两种方式调用RunnablePassthrough &#xff08;1&#…

【three.js】手把手带你理解制作一个3D场景 超级详细

我们主要目的是制作这样一个三维模型: 我们直接上代码,从代码中一点点解释模型是如何一步一步制作的。 // 引入three.js import * as THREE from three; /*** 创建3D场景对象Scene*/ const scene = new THREE.Scene();/*** 创建网格模型*/ //创建一个长方体几何对象Geometry…

安卓使用ExoPlayer出现膨胀类异常

1.导包 implementation com.google.android.exoplayer:exoplayer-core:2.15.1implementation com.google.android.exoplayer:exoplayer-ui:2.15.1 2.在Androidifest.xml加入权限&#xff0c;我这里加了忘了与读写权限 <uses-permission android:name"android.permissio…

ESG工具变量:最早一期、同城ESG(2009-2022年)

参照《管理评论》中席龙胜&#xff08;2022&#xff09;、《证券市场导报》中王琳璘&#xff08;2022&#xff09;的做法&#xff0c;选择企业同城市其他上市企业ESG的平均表现、企业最早一期ESG表现作为企业ESG表现的工具变量 一、数据介绍 数据名称&#xff1a;ESG工具变量—…

yolov9从头开始训练

yolov9从头开始训练 一、准备数据集 数据集相关文件存放布局如下 yolov9-datasets ├── train │ ├── images │ │ ├── image.jpg │ │ ├── │ └── labels │ ├── image.txt │ ├── ├── valid │ ├── images │ │ ├── image.jpg │ │ ├─…

项目运维方案

1. 文档介绍 2. 人员与责任 3. 运维过程内容 4. 运维资源 5. 运维服务规划保障 6. 事件处置 7. 质量改进 8. 运维边界及内容 软件开发全套资料获取&#xff1a;软件开发全套资料_数字中台建设指南-CSDN博客

CSP-201803-2-碰撞的小球

CSP-201803-2-碰撞的小球 解题思路 解题思路是通过模拟小球在数轴上的移动来计算t秒后各个小球的位置。 初始化阶段&#xff1a;首先&#xff0c;读入小球的数量 n、线段长度 L 和时间 t。然后&#xff0c;对于每个小球&#xff0c;程序读入它们的初始位置&#xff0c;并创建一…

【学习笔记】数据结构与算法05:树、层序遍历、深度优先搜索、二叉搜索树

知识出处&#xff1a;Hello算法&#xff1a;https://www.hello-algo.com/ 文章目录 2.4 树2.4.1 「二叉树 binary tree」2.4.1.1 二叉树基本操作2.4.1.2 二叉树的常见类型「完美二叉树 perfect binary tree」「完全二叉树 complete binary tree」「完满二叉树 full binary tre…

【每日刷题】数组-LC56、LC238、随想录1

1. LC56 合并区间 题目链接 Arrays.sort先让intervals里的子数组按照子数组的第一个数字值从小到大排列。开一个新数组&#xff0c;newInterval&#xff0c;存放合并好的子数组让intervals的当前子数组i的第一个数字与newInterval的当前子数组index的最后一个数字比较大小&am…

JAVA对象内存模型

Java对象内存模型 > 一个Java对象在内存中包括3个部分&#xff1a;对象头、实例数据和对齐填充 > > 数据 内存 – CPU 寄存器 -127 补码 10000001 - 11111111 32位的处理器 一次能够去处理32个二进制位 4字节的数据 64位操作系统 8字节 2的64次方的寻址空间 指针压…

【C++】核心编程--内存分区、引用

文章目录 1.内存分区模型1.1 程序运行前1.1.1 代码区1.1.2 全局区 1.2 程序运行后1.2.1 栈区1.2.2 堆区 1.3 new操作符 2. 引用2.1 给变量起别名2.2 引用做函数参数2.3 引用做函数返回值2.4 引用的本质2.25 常量引用 1.内存分区模型 C程序在执行时&#xff0c;将内存大方向划分…

第七十一天 漏洞发现-Web框架中间件联动GobyAfrogXrayAwvsVulmap

第71天 漏洞发现-Web框架中间件&联动&Goby&Afrog&Xray&Awvs&Vulmap 知识点&#xff1a; 1、Bup简单介绍&使用说明 2、Xray简单介绍&使用说明 3、AWWS简单介绍&使用说明 4、Goby简单介绍&使用说明 5、Afrog简单介绍&使用说明 6、…

Socket网络编程(五)——TCP数据发送与接收并行

目录 主要实现需求TCP 服务端收发并行重构启动main方法重构重构分离收发消息的操作重构接收消息的操作重构发送消息TCPServer调用发送消息的逻辑监听客户端链接逻辑重构Socket、流的退出与关闭 TCP 客户端收发并行重构客户端 main函数重构客户端接收消息重构客户端发送消息重构…

日常科研中经常使用的命令

Linux目录树状结构 1. Windows是磁盘分区&#xff0c;Linux不区分盘符&#xff0c;所有文件都在根目录斜线下面&#xff1b; 2. 根目录显示不同&#xff0c;Linux是一个斜线&#xff0c;而windows是盘符&#xff0c;然后冒号&#xff1b; 3. 分割目录Linux用斜线&#xff0c…

Odoo迈入开源第一低代码开发平台的重要里程碑

Odoo17的正式发布已经过去好几个月了&#xff0c;通过一段时间的运用&#xff0c;最大的感触就是&#xff0c;Odoo会成为企业管理软件低代码开发平台的重要一员&#xff0c;而V17则会成为这个过程中具有里程碑意义的版本。 时隔四个月&#xff0c;让我们回头来看看Odoo17带来的…

国防科大、中大0706大气科学及南信大大物院初试复习宝典——简答题知识点汇总

Attention&#xff01;有思维导图版 有Xmind导图格式的&#xff0c;更适合复习&#xff0c;下面是xmind导出的markdown格式&#xff0c;丑死了&#xff0c;可以移步去网盘查看 链接&#xff1a;https://pan.baidu.com/s/1ZcqfPWoyMd6eXf3_jvSVzQ?pwd7ij7 提取码&#xff1a;…

Node.js基础---Express中间件

1. 概念 1.什么是中间件 中间件(Middleware)&#xff0c;特指业务流程的中间处理环节 2. Express 中间件的调用流程 当一个请求到达 Express 的服务器后&#xff0c;可以连续调用多个中间件&#xff0c;从而对这次请求进行预处理 3. Express 中间件格式 Express 的中间件&…