首页 > 编程语言 >数据结构之栈和队列算法题

数据结构之栈和队列算法题

时间:2024-12-17 16:59:31浏览次数:6  
标签:pq obj 队列 之栈 st Queue int return 数据结构

一:有效括号数

学了栈之后这一题就比较简单了。

思路:1、左括号进栈 2、右括号出栈匹配。

完整代码:

因为使用C语言写的,所以里面包含了栈的实现

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

typedef int STDataType;
typedef struct Stack
{
	STDataType* a;
	int top;
	int capacity;
}ST;

void StackInit(ST* st);

void StackPush(ST* st, STDataType x);

void StackPop(ST* st);

STDataType StackTop(ST* st);

bool StackEmpty(ST* st);

void StackDestroy(ST* st);

int StackSize(ST* st);


void StackInit(ST* st)
{
	st->a = NULL;
	//top 表示栈顶元素的下一个
	st->capacity = st->top = 0;
}

void StackPush(ST* st, STDataType x)
{
	assert(st);
	if (st->top == st->capacity)
	{
		int newcapacity = st->capacity == 0 ? 4 : st->capacity * 2;
		STDataType* tmp = (STDataType*)realloc(st->a, newcapacity*sizeof(STDataType));
		if (tmp == NULL)
		{
			perror("malloc fail!!");
			exit(1);
		}
		st->a = tmp;
		st->capacity = newcapacity;
	}
	st->a[st->top++] = x;
}

void StackPop(ST* st)
{
	assert(st);

	assert(!StackEmpty(st));

	st->top--;
}

STDataType StackTop(ST* st)
{
	assert(st);
	assert(!StackEmpty(st));

	return st->a[st->top - 1];
}

bool StackEmpty(ST* st)
{
	assert(st);

	return st->top == 0;
}

void StackDestroy(ST* st)
{
	assert(st);

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

int StackSize(ST* st)
{
	assert(st);
	return st->top;
}

bool isValid(char* s) {
    ST st;
    StackInit(&st);
    while(*s)
    {
        if(*s=='{'
        || *s=='('
        || *s=='[')
        {
            StackPush(&st,*s);
        }
        else
        {
            if(StackEmpty(&st))
            {
                StackDestroy(&st);
                return false;
            }
            char c = StackTop(&st);
            StackPop(&st);
            if((c == '{' && *s != '}')
            || (c == '(' && *s != ')') 
            || (c == '[' && *s != ']'))
            {
                StackDestroy(&st);
                return false;
            }
        }
        s++;
    }
    bool ret = StackEmpty(&st);
    StackDestroy(&st);
    return ret;
}

二:用队列实现栈

首先说明一点,这只是对栈和队列熟练度的考察,并不是栈的更好地实现方式。

思路:两个队列,保证有一个队列为空,然后其余操作基于空队列实现。

画图分析:

完整代码:

typedef int QDatatype;

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

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


void QueueInit(Queue* pq);
void QueueDestroy(Queue* pq);
void QueuePush(Queue* pq, QDatatype x);
void QueuePop(Queue* pq);
QDatatype QueueFront(Queue* pq);
QDatatype Queueback(Queue* pq);
int QueueSize(Queue* pq);
bool QueueEmpty(Queue* pq);

void QueueInit(Queue* pq)
{
	assert(pq);
	pq->head = NULL;
	pq->tail = NULL;
}
void QueueDestroy(Queue* pq)
{
	assert(pq);
	QueueNode* cur = pq->head;
	while (cur)
	{
		QueueNode* next = cur->next;
		free(cur);
		cur = next;
	}
	pq->head = pq->tail = NULL;
}
void QueuePush(Queue* pq, QDatatype x)
{
	assert(pq);
	QueueNode* newnode = (QueueNode*)malloc(sizeof(QueueNode));
	if (newnode == NULL)
	{
		perror("malloc fail!!");
		exit(1);
	}
	else
	{
		newnode->next = NULL;
		newnode->data = x;
	}
	if (pq->head == NULL)
	{
		pq->head = pq->tail = newnode;
	}
	else
	{
		pq->tail->next = newnode;
		pq->tail = newnode;
	}
}
void QueuePop(Queue* pq)
{
	assert(pq);
	assert(pq->head != NULL);

	QueueNode* del = pq->head;
	pq->head = del->next;
	free(del);
	del = NULL;
	if (pq->head == NULL)
	{
		pq->tail = NULL;
	}
}
QDatatype QueueFront(Queue* pq)
{
	assert(pq);
	assert(pq->head != NULL);

	return pq->head->data;
}
QDatatype Queueback(Queue* pq)
{
	assert(pq);
	assert(pq->head != NULL);

	return pq->tail->data;
}
int QueueSize(Queue* pq)
{
	assert(pq);
	int cnt = 0;
	QueueNode* cur = pq->head;
	while (cur)
	{
		cnt++;
		cur = cur->next;
	}
	return cnt;
}
bool QueueEmpty(Queue* pq)
{
	assert(pq);
	return pq->head == NULL;
}


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


MyStack* myStackCreate() 
{
    //不能直接创建结构体,出函数栈帧销毁
    MyStack* st = (MyStack*)malloc(sizeof(MyStack));
    QueueInit(&st->q1);
    QueueInit(&st->q2);
    return st;
}

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

int myStackPop(MyStack* obj) {
	//判空
	Queue *Empty = &obj->q1;
	Queue *NonoEmpty = &obj->q2;
	if (!QueueEmpty(Empty))
	{
		Empty = &obj->q2;
		NonoEmpty = &obj->q1;
	}
	//出队列,入另外一个队列
	while (QueueSize(NonoEmpty) > 1)
	{
		QDatatype data = QueueFront(NonoEmpty);
		QueuePush(Empty, data);
		QueuePop(NonoEmpty);
	}
	//剩余一个元素
	QDatatype data = QueueFront(NonoEmpty);
	QueuePop(NonoEmpty);
	return data;
}

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);
}

/**
 * Your MyStack struct will be instantiated and called as such:
 * MyStack* obj = myStackCreate();
 * myStackPush(obj, x);
 
 * int param_2 = myStackPop(obj);
 
 * int param_3 = myStackTop(obj);
 
 * bool param_4 = myStackEmpty(obj);
 
 * myStackFree(obj);
*/

三:用栈实现队列

这一题就是反过来用栈实现队列,要实现后进先出。

思路:两个栈pushst popst 然后往pushst里面push ,每当要出队列或者要去队头数据时,就返回popst的栈顶数据,如果popst为空,就一口气把pushst里面的数据全塞进去。

就不画图了

完整代码:

栈的实现在上面有,不重复拷贝了。

typedef struct {
    ST pushst;
    ST popst;
} MyQueue;


MyQueue* myQueueCreate() {
    MyQueue* pq = (MyQueue*)malloc(sizeof(MyQueue));
    StackInit(&pq->pushst);
    StackInit(&pq->popst);
    return pq;
}

void myQueuePush(MyQueue* obj, int x) {
    StackPush(&obj->pushst,x);
}

int myQueuePop(MyQueue* obj) {
    if(StackEmpty(&obj->popst))
    {
        while(!StackEmpty(&obj->pushst))
        {
            StackPush(&obj->popst,StackTop(&obj->pushst));
            StackPop(&obj->pushst);
        }
    }
    int frontstack = StackTop(&obj->popst);
    StackPop(&obj->popst);
    return frontstack;
}

int myQueuePeek(MyQueue* obj) {
    if(StackEmpty(&obj->popst))
    {
        while(!StackEmpty(&obj->pushst))
        {
            StackPush(&obj->popst,StackTop(&obj->pushst));
            StackPop(&obj->pushst);
        }
    }
    return StackTop(&obj->popst);
}

bool myQueueEmpty(MyQueue* obj) {
    return StackEmpty(&obj->popst) && StackEmpty(&obj->pushst);
}

void myQueueFree(MyQueue* obj) {
    StackDestroy(&obj->popst);
    StackDestroy(&obj->pushst);
    free(obj);
}

四:环形队列(环形缓冲器)

这里给大家贴一张图:

(数组实现)思路:创建K(存有效数据的大小)+1的长度,两个指针(严格来讲应该是下标)指向头和尾。然后用%操作实现循环。

具体请看下面画图分析

画图分析:

完整代码:


typedef struct {
    int* a;
    int tail;
    int head;
    int k;
} MyCircularQueue;

bool myCircularQueueIsEmpty(MyCircularQueue* obj);
bool myCircularQueueIsFull(MyCircularQueue* obj);
MyCircularQueue* myCircularQueueCreate(int k) {
    MyCircularQueue* cp =(MyCircularQueue*)malloc(sizeof(MyCircularQueue));
    cp->a =(int*)malloc(sizeof(int)*(k+1));
    cp->tail = 0;
    cp->head = 0;
    cp->k = k;
    return cp;
}

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

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

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

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

bool myCircularQueueIsEmpty(MyCircularQueue* obj) {
    return obj->head == obj->tail;
}

bool myCircularQueueIsFull(MyCircularQueue* obj) {
    return (obj->tail+1)%(obj->k+1) == obj->head;
}

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

  完

标签:pq,obj,队列,之栈,st,Queue,int,return,数据结构
From: https://blog.csdn.net/2403_87718362/article/details/144510713

相关文章

  • 分布式消息队列Kafka
    什么是KafkaKafka是一个分布式的、分区的、多副本的、基于发布/订阅模式的消息队列系统。它最初由LinkedIn开发,后来成为Apache的开源项目。主要用于处理大规模的实时数据,能够高效地处理大量的消息传递。例如,在一个电商平台中,用户的下单信息、商品浏览记录等数据可以通过Kafka......
  • 数据结构复习总结(期末前更新)
    搜索二叉树#include<bits/stdc++.h>usingnamespacestd;structTreeNode{ intval; TreeNode*left; TreeNode*right; TreeNode(intx):val(x),left(nullptr),right(nullptr){}};//搜索二叉树//每个节点的左子树中的所有节点值都小于该节点的值,而右子树......
  • [Done] 省选数据结构题目的做
    这个系列用于记录学习省选知识点的过程中做题的笔记,系列名就是这样因为省选的知识点真的是又多又杂,题单也是又难又长,不排除同时多个题单一起开工的情况,所以如果这一部分完成了就是[done]的前缀,做中就是[working]可能会跳过一些lxl题2024.12.15基本完成,剩下一些零散知识......
  • 【初阶数据结构与算法】八大排序算法之选择排序(直接选择排序、堆排)
    文章目录一、单向直接选择排序二、双向直接选择排序三、堆排四、直接选择排序以及堆排性能对比一、单向直接选择排序   选择排序很好理解,就是按照字面意思来,比如我们想要将一个数组排成升序,那么小的值就会被放在前面,我们就可以每次都找到数组中的最小值,把它往前......
  • 【数据结构】八大排序
    目录一、直接插入排序二、希尔排序三、选择排序四、堆排序五、冒泡排序六、快速排序七、归并排序八、计数排序稳定性结论稳定性:排序后相同元素之间的相对顺序是否保持不变。一、直接插入排序基本思想:通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找......
  • 数据结构树
    文章目录树树的性质二叉树......
  • ADT栈与队列的编程与实现
    ADT栈与队列的编程与实现一实验目的:加深对抽象数据类型ADT栈和队列的理解。二实验环境:MicrosoftVisualC++2010三实验内容:编写程序实现ADT栈的定义,及常用操作(数组或指针实现):生成栈;PushPop编写程序实现ADT队列的定义,及常用操作:生成队列;Enqueues入列;Isemp......
  • 商城项目基于消息队列的TCC分布式事务控制改造-----商城项目
    packagecom.alatus.mall.ware.service.impl;importcom.alatus.common.to.mq.StockDetailTo;importcom.alatus.common.to.mq.StockLockedTo;importcom.alatus.common.utils.R;importcom.alatus.common.exception.NoStockException;importcom.alatus.mall.ware.conf......
  • 【数据结构与算法】Java描述:JDK17新增常用特性
    前言:从springboot3.0开始,已经不支持JDK8了。参考资料,来自官方博客:https://spring.io/blog/2022/01/20/spring-boot-3-0-0-m1-is-nowavailable?spm=a2c6h.12873639.article-detail.24.766d46b40LM1IV从3.0开始,转变为JDK17。JDK17是LTS(长期支持版),可以免费商用到2029......
  • 【初阶数据结构和算法】八大排序算法之插入排序(直接插入排序、希尔排序及其对比)
    文章目录一、常见排序算法分类一、直接插入排序二、希尔排序三、直接插入排序和希尔排序性能对比一、常见排序算法分类   常见的排序算法有八种,我们简单盘点一下插入排序:直接插入排序、希尔排序选择排序:直接选择排序、堆排序交换排序:冒泡排序、快排希尔排序计数......