栈和队列OJ题目

括号匹配问题

问题描述

https://leetcode-cn.com/problems/valid-parentheses/

思路分析

遇到左括号就入栈,遇到右括号就取出栈顶元素与之相比,如果不配对就返回假,否则继续。需要判断一些特殊情况,比如全是左括号。

代码解析

本代码是用C语言写的,需要在前面添加栈的实现相关函数。

bool isValid(char * s)
{
    ST st;
    StackInit(&st);
    while(*s)
    {
        //当s没有走到末尾
        if(*s=='('||*s=='['||*s=='{')
        {
            //左括号就入栈
            StackPush(&st,*s);
        }
        else
        {
            //右括号就出栈,与栈顶元素比较
            if(StackEmpty(&st))
            {
                //如果栈空就不符合
                StackDestroy(&st);
                return false;
            }
            char top=StackTop(&st);
            StackPop(&st);
            //查看是否满足条件
            if((*s==')'&&top=='(') || 
                (*s==']'&&top=='[')||
                (*s=='}'&&top=='{'))
            {
                //continue;//匹配正确就继续
            }
            else
            {
                StackDestroy(&st);
                return false;
            }
        }
        s++;
    }
    //全部检查一遍后,栈不为空,说明还有未配对的左括号
    if(!StackEmpty(&st))
    {
        //栈不为空
        StackDestroy(&st);
        return false;
    }
    else
    {
        StackDestroy(&st);
        return true;
    }
    
}

用队列实现栈

问题描述

https://leetcode-cn.com/problems/implement-stack-using-queues/

在这里插入图片描述

思路分析

用两个队列实现栈,首先明确栈和队列的特点,栈–后进先出,队列–先进先出。那么设置两个队列,设元素个数为n。

  1. 入数据,入数据到一个不为空队列,如果两个队列都为空,入哪一个都行。
  2. 出数据,将不为空的队列的前n-1个数据导入空的队列,输出最后一个数。
  3. 出入数据按照1和2执行,如此循环即可。

代码解析

使用C语言的话,前面需要导入队列的实现

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) {
    //出数据,将不为空的队列的前n-1个数据导入空的队列,输出最后一个数
    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) {
    //获取栈顶元素,其实就是非空队列的组后一个元素
    Queue* emptyq=&(obj->q1);
    Queue* nonemptyq=&(obj->q2);
    if(!QueueEmpty(&(obj->q1)))
    {
        emptyq=&(obj->q2);
        nonemptyq=&(obj->q1);
    }
    return QueueBack(nonemptyq);
}

bool myStackEmpty(MyStack* obj) {
    //两个队列都为空才是空
    return QueueEmpty(&(obj->q1))&&QueueEmpty(&(obj->q2));
}

void myStackFree(MyStack* obj) {
    //先释放队列,再释放栈
    QueueDestroy(&(obj->q1));
    QueueDestroy(&(obj->q2));
    free(obj);
}

用栈实现队列

问题描述

https://leetcode-cn.com/problems/implement-queue-using-stacks/

在这里插入图片描述

思路分析

同样是用两个栈实现一个队列,需牢记它们的各自的特点,与上题有略微不同,我们设置一个入栈pushST和一个出栈popST

  1. 入数据,只往pushST入
  2. 出数据,如果popST不为空,直接出栈;如果popST为空,将pushST数据倒入,再出栈

画图分析

在这里插入图片描述

代码解析

使用C语言实现的话,前面也需实现栈

typedef struct {
    //一个入数据栈,一个出数据栈
    ST pushST;
    ST popST;
} MyQueue;
int myQueuePeek(MyQueue* obj);

MyQueue* myQueueCreate() {
    MyQueue* q=(MyQueue*)malloc(sizeof(MyQueue));
    //分别初始化
    StackInit(&(q->pushST));
    StackInit(&(q->popST));
    return q;
}

void myQueuePush(MyQueue* obj, int x) {
    //入数据,只往pushST入
    StackPush(&(obj->pushST),x);
}

int myQueuePop(MyQueue* obj) {
    // //出数据,如果popST不为空,直接出栈;如果popST为空,将pushST数据倒入,再出栈
    // if(StackEmpty(&(obj->popST)))
    // {
    //     //为空
    //     //开倒
    //     while(!StackEmpty(&(obj->pushST)))
    //     {
    //         StackPush(&(obj->popST),StackTop(&(obj->pushST)));
    //         StackPop(&(obj->pushST));
    //     }
    // }
    //可直接调用peek函数倒数据
    int front=myQueuePeek(obj);
    //不为空就出栈
    StackPop(&(obj->popST));
    return front;
}

int myQueuePeek(MyQueue* obj) {
    //返回队头元素
    //如果popST为空,将pushST数据倒入,再出栈
    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->pushST))&&StackEmpty(&(obj->popST));
}

void myQueueFree(MyQueue* obj) {
    StackDestroy(&(obj->pushST));
    StackDestroy(&(obj->popST));
    free(obj);
}

设计循环队列

问题描述

https://leetcode-cn.com/problems/design-circular-queue/

在这里插入图片描述

思路分析

  1. 用顺序表实现
  2. 用循环链表实现

需要注意的是如何判断满和空

代码解析

顺序表实现

typedef int CQDataType;
typedef struct 
{
	int* a;//数组
	int front;//头
	int rear;//尾
	int capacity;//容量
} MyCircularQueue;
bool myCircularQueueIsEmpty(MyCircularQueue* obj);
bool myCircularQueueIsFull(MyCircularQueue* obj);
//创建循环队列
MyCircularQueue* myCircularQueueCreate(int k)
{
	MyCircularQueue* cq = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));
	if (cq == NULL)
		exit(-1);
	cq->a = (CQDataType*)malloc(sizeof(CQDataType) * (k + 1));
	//多开辟一个空间,用以区分满和空
	if (cq->a == NULL)
		exit(-1);
	cq->capacity = k ;
	cq->front = cq->rear = 0;
	return cq;
}
//入队列
bool myCircularQueueEnQueue(MyCircularQueue* obj, int value)
{
	//判断是否满
	if (myCircularQueueIsFull(obj))
		return false;
	//插入
	obj->a[obj->rear] = value;
	obj->rear = (obj->rear + 1) % (obj->capacity + 1);
	return true;
}
//出队列
bool myCircularQueueDeQueue(MyCircularQueue* obj)
{
	
	if (myCircularQueueIsEmpty(obj))
	{
		//为空
		return false;
	}
	obj->front = (obj->front + 1) % (obj->capacity + 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;
	//取rear的前一个
	return obj->a[(obj->rear + obj->capacity) % (obj->capacity + 1)];
}
//判断是否为空
bool myCircularQueueIsEmpty(MyCircularQueue* obj)
{
	if (obj->front == obj->rear)
		return true;
	else
		return false;
}
//判断队列是否满
bool myCircularQueueIsFull(MyCircularQueue* obj)
{
	if ((obj->rear + 1) % (obj->capacity + 1) == obj->front)
		return true;
	else
		return false;
}
//销毁队列
void myCircularQueueFree(MyCircularQueue* obj)
{
	free(obj->a);
	obj->capacity = obj->front = obj->rear = 0;
	free(obj);
	obj = NULL;
}

链表实现

//链表实现
typedef int CQDataType;
typedef struct MyCircularQueueNode
{
	CQDataType data;
	struct MyCircularQueueNode* next;
}MyCQNode;
typedef struct
{
	
	MyCQNode* head;//指向循环队列的头的前一个
	MyCQNode* tail;//指向尾
	int capacity;//容量
} MyCircularQueue;


//创建循环队列
MyCircularQueue* myCircularQueueCreate(int k);
//入队列
bool myCircularQueueEnQueue(MyCircularQueue* obj, int value);
//出队列
bool myCircularQueueDeQueue(MyCircularQueue* obj);
//取队头元素
int myCircularQueueFront(MyCircularQueue* obj);
//取队尾元素
int myCircularQueueRear(MyCircularQueue* obj);
//判断是否为空
bool myCircularQueueIsEmpty(MyCircularQueue* obj);
//判断队列是否满
bool myCircularQueueIsFull(MyCircularQueue* obj);
//销毁队列
void myCircularQueueFree(MyCircularQueue* obj);

//链表实现
//创建循环队列
MyCircularQueue* myCircularQueueCreate(int k)
{
	MyCircularQueue* cq = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));
	if (cq == NULL)
		exit(-1);
	cq->capacity = k;
	//开辟k+1个结点
	//先一个
	MyCQNode* head = (MyCQNode*)malloc(sizeof(MyCQNode));
	if (head == NULL)
		exit(-1);
	head->next = NULL;
	MyCQNode* sur = head;
	
	while (k--)
	{
		//再开K个
		MyCQNode* newnode = (MyCQNode*)malloc(sizeof(MyCQNode));
		if (newnode == NULL)
			exit(-1);
		newnode->next = NULL;
		sur->next = newnode;
		sur = sur->next;

	}
	sur->next = head;//循环链表
	cq->head = cq->tail = head;//最初都指向第一个
	return cq;
}
//入队列
bool myCircularQueueEnQueue(MyCircularQueue* obj, int value)
{
	if (myCircularQueueIsFull(obj))
		return false;
	//tail指向的下一个位置加入
	obj->tail->next->data = value;
	obj->tail = obj->tail->next;
	return true;
}
//出队列
bool myCircularQueueDeQueue(MyCircularQueue* obj)
{
	if (myCircularQueueIsEmpty(obj))
		return false;
	obj->head = obj->head->next;
	return true;
}
//取队头元素
int myCircularQueueFront(MyCircularQueue* obj)
{
	if (myCircularQueueIsEmpty(obj))
		return -1;
	//head指向的下一个结点数据
	return obj->head->next->data;
}
//取队尾元素
int myCircularQueueRear(MyCircularQueue* obj)
{
	if (myCircularQueueIsEmpty(obj))
		return -1;
	return obj->tail->data;
}
//判断是否为空
bool myCircularQueueIsEmpty(MyCircularQueue* obj)
{
	if (obj->head == obj->tail)
		return true;
	else
		return false;
}
//判断队列是否满
bool myCircularQueueIsFull(MyCircularQueue* obj)
{
	if (obj->head == obj->tail->next)
		return true;
	else
		return false;
}
//销毁队列
void myCircularQueueFree(MyCircularQueue* obj)
{
	MyCQNode* temp = obj->head;
	MyCQNode* headnext = obj->head->next;
	temp->next = NULL;//断链
	while (headnext != NULL)
	{
		temp = headnext->next;
		free(headnext);
		headnext = temp;
	}
	obj->capacity = 0;
	obj->head = obj->tail = NULL;
	free(obj);
	obj = NULL;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

s_persist

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值