经典栈和队列OJ题

目录

1、括号匹配问题

2、用栈实现队列

队列

3、用队列实现栈

4、设计循环队列


1、括号匹配问题

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

有效字符串需满足:

  1. 左括号必须用相同类型的右括号闭合。
  2. 左括号必须以正确的顺序闭合。
  3. 每个右括号都有一个对应的相同类型的左括号。

思路:

利用栈的后进先出,边进边出的性质

将左括号存入栈中,后进入的左括号先出来,与右括号进行匹配

objectivec 复制代码
// 支持动态增长的栈
typedef char STDataType;
typedef struct Stack
{
	STDataType* _a;
	int _top;		// 栈顶
	int _capacity;  // 容量 
}Stack;
 
// 初始化栈 
void StackInit(Stack* ps)
{
	assert(ps);
	ps->_a = NULL;
	ps->_top = ps->_capacity = 0;
}
 
//动态申请
void Stackcapacity(Stack* ps)
{
	if (ps->_top == ps->_capacity)
	{
		ps->_capacity = ps->_capacity == 0 ? 4 : 2 * ps->_capacity;
		STDataType* tmp = (STDataType*)realloc(ps->_a, ps->_capacity * sizeof(STDataType));
		if (tmp == NULL)
		{
			perror("Stackcapacity()::realloc()");
			return;
		}
		ps->_a = tmp;
	}
}
 
// 入栈 
void StackPush(Stack* ps, STDataType data)
{
	assert(ps);
	Stackcapacity(ps);//动态申请
	ps->_a[ps->_top] = data;
	ps->_top++;
}
 
// 出栈 
void StackPop(Stack* ps)
{
	assert(ps);
	if (ps->_top == 0)
	{
		printf("栈已空\n");
		return;
	}
	ps->_top--;
}
 
// 获取栈顶元素 
STDataType StackTop(Stack* ps)
{
	assert(ps);
	assert(ps->_top != 0);
	return ps->_a[ps->_top - 1];
}
 
// 获取栈中有效元素个数 
int StackSize(Stack* ps)
{
	assert(ps);
	return ps->_top;
}
 
// 检测栈是否为空,如果为空返回非零结果,如果不为空返回0 
int StackEmpty(Stack* ps)
{
	assert(ps);
	if (ps->_top == 0)
		return 1;
	else
		return 0;
}
 
// 销毁栈 
void StackDestroy(Stack* ps)
{
	assert(ps);
	free(ps->_a);
	ps->_a = NULL;
	ps->_top = ps->_capacity = 0;
}

bool isValid(char* s) {
    Stack stack;
    StackInit(&stack);
    for(int i = 0;i<strlen(s);i++)
    {
        if(s[i] == '('||s[i] == '['||s[i] == '{')//栈存左括号
        {
            StackPush(&stack,s[i]);
            continue;//已经push,就进行下一次循环,判断下一个括号
        }
        if(StackEmpty(&stack))//栈空了,当前无左括号,与右括号匹配
        {
            StackDestroy(&stack);//return前要destroy,leetcode内存泄漏不报错
            return  false;
        }
        char a = StackTop(&stack);
        StackPop(&stack);
        if(a == '('&&s[i] != ')'||a == '['&&s[i] != ']'||a == '{'&&s[i] != '}')
        {
            StackDestroy(&stack);
            return  false;
        }
    }
    if(!StackEmpty(&stack))//匹配完后,栈里多了左括号
    {
        StackDestroy(&stack);
        return  false;
    }
    return true;
}

2、用栈实现队列

仅使用两个栈 实现先入先出队列。队列应当支持一般队列支持的所有操作(pushpoppeekempty):

实现 MyQueue 类:

  • void push(int x) 将元素 x 推到队列的末尾
  • int pop() 从队列的开头移除并返回元素
  • int peek() 返回队列开头的元素
  • boolean empty() 如果队列为空,返回 true ;否则,返回 false

思路:

一个栈push,一个栈pop(当pop没有元素时,push的全部元素转移到pop),

pop的栈顶元素就是队头元素(因为已逆置)

destroy时,注意指针里有指针

objectivec 复制代码
// 支持动态增长的栈
typedef int STDataType;
typedef struct Stack
{
	STDataType* _a;
	int _top;		// 栈顶
	int _capacity;  // 容量 
}Stack;
 
// 初始化栈 
void StackInit(Stack* ps)
{
	assert(ps);
	ps->_a = NULL;
	ps->_top = ps->_capacity = 0;
}
 
//动态申请
void Stackcapacity(Stack* ps)
{
	if (ps->_top == ps->_capacity)
	{
		ps->_capacity = ps->_capacity == 0 ? 4 : 2 * ps->_capacity;
		STDataType* tmp = (STDataType*)realloc(ps->_a, ps->_capacity * sizeof(STDataType));
		if (tmp == NULL)
		{
			perror("Stackcapacity()::realloc()");
			return;
		}
		ps->_a = tmp;
	}
}
 
// 入栈 
void StackPush(Stack* ps, STDataType data)
{
	assert(ps);
	Stackcapacity(ps);//动态申请
	ps->_a[ps->_top] = data;
	ps->_top++;
}
 
// 出栈 
void StackPop(Stack* ps)
{
	assert(ps);
	if (ps->_top == 0)
	{
		printf("栈已空\n");
		return;
	}
	ps->_top--;
}
 
// 获取栈顶元素 
STDataType StackTop(Stack* ps)
{
	assert(ps);
	assert(ps->_top != 0);
	return ps->_a[ps->_top - 1];
}
 
// 获取栈中有效元素个数 
int StackSize(Stack* ps)
{
	assert(ps);
	return ps->_top;
}
 
// 检测栈是否为空,如果为空返回非零结果,如果不为空返回0 
int StackEmpty(Stack* ps)
{
	assert(ps);
	if (ps->_top == 0)
		return 1;
	else
		return 0;
}
 
// 销毁栈 
void StackDestroy(Stack* ps)
{
	assert(ps);
	free(ps->_a);
	ps->_a = NULL;
	ps->_top = ps->_capacity = 0;
}

typedef struct {
    Stack push;
    Stack pop;
} MyQueue;


MyQueue* myQueueCreate() {
    MyQueue* obj = (MyQueue*)malloc(sizeof(MyQueue));
    StackInit(&(obj->push));
    StackInit(&(obj->pop));
    return obj;
}

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

bool myQueueEmpty(MyQueue* obj) {
    if(StackEmpty(&(obj->push))&&StackEmpty(&(obj->pop)))
    return true;
    else
    return false;
}

int myQueuePop(MyQueue* obj) {
    if(myQueueEmpty(obj))
    return -1;
    int x = myQueuePeek(obj);
    StackPop(&(obj->pop));
    return x;
}

int myQueuePeek(MyQueue* obj) {
    if(myQueueEmpty(obj))
    return -1;
    if(StackEmpty(&(obj->pop)))
    while(!StackEmpty(&(obj->push)))
    {
        StackPush(&(obj->pop),StackTop(&(obj->push)));
        StackPop(&(obj->push));
    }
    return StackTop(&(obj->pop));
}

void myQueueFree(MyQueue* obj) {
    StackDestroy(&(obj->push));
    StackDestroy(&(obj->pop));
    free(obj);
}

/**
 * Your MyQueue struct will be instantiated and called as such:
 * MyQueue* obj = myQueueCreate();
 * myQueuePush(obj, x);
 
 * int param_2 = myQueuePop(obj);
 
 * int param_3 = myQueuePeek(obj);
 
 * bool param_4 = myQueueEmpty(obj);
 
 * myQueueFree(obj);
*/

队列

3、用队列实现栈

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

实现 MyStack 类:

  • void push(int x) 将元素 x 压入栈顶。
  • int pop() 移除并返回栈顶元素。
  • int top() 返回栈顶元素。
  • boolean empty() 如果栈是空的,返回 true ;否则,返回 false

思路:

元素全push到一个队列里,保持一个非空队列,一个空队列,但不是固定的,因为会转移元素

栈顶元素,调用非空队列的queueback(),

删除栈顶元素,把非空队列的元素转移到空队列,当非空队列只有一个元素时,跳出循环,保存栈顶元素,pop掉栈顶元素

destroy时,注意指针里有指针

objectivec 复制代码
typedef int QDataType;
// 链式结构:表示队列 
typedef struct QListNode
{
	struct QListNode* _next;
	QDataType _data;
}QNode;
 
// 队列的结构 
typedef struct Queue
{
	QNode* _front;
	QNode* _rear;
	int size;
}Queue;

// 初始化队列 
void QueueInit(Queue* q)
{
	assert(q);
	q->_front = q->_rear = NULL;
	q->size = 0;
}
 
// 队尾入队列 
void QueuePush(Queue* q, QDataType data)
{
	assert(q);
	QNode* tmp = (QNode*)malloc(sizeof(QNode));
	if (tmp == NULL)
	{
		perror("QueueNode()::malloc()");
		return;
	}
	tmp->_next = NULL;
	tmp->_data = data;
	if (q->size == 0)
	{
		q->_front = q->_rear = tmp;
	}
	else
	{
		q->_rear->_next = tmp;
		q->_rear = tmp;
	}
	q->size++;
}
 
// 队头出队列 
void QueuePop(Queue* q)
{
	assert(q);
	if (q->size == 0)
	{
		printf("队列已空\n");
		return;
	}
	QNode* del = q->_front;
	q->_front = q->_front->_next;
	if (q->_front == NULL)
	{
		q->_rear = NULL;
	}
	free(del);
	del = NULL;
	q->size--;
}
 
// 获取队列头部元素 
QDataType QueueFront(Queue* q)
{
	assert(q);
	assert(q->_front);
	return q->_front->_data;
}
 
// 获取队列队尾元素 
QDataType QueueBack(Queue* q)
{
	assert(q);
	assert(q->_rear);
	return q->_rear->_data;
}
 
// 获取队列中有效元素个数 
int QueueSize(Queue* q)
{
	return q->size;
}
 
// 检测队列是否为空,如果为空返回非零结果,如果非空返回0 
int QueueEmpty(Queue* q)
{
	if (q->size == 0)
		return 1;
	else
		return 0;
}
 
// 销毁队列 
void QueueDestroy(Queue* q)
{
	while (q->_front)
	{
		QNode* del = q->_front;
		q->_front = q->_front->_next;
		free(del);
	}
	q->_rear = NULL;
	q->size = 0;
}


typedef struct {
    Queue Q1;
    Queue Q2;
} MyStack;


MyStack* myStackCreate() {
    MyStack* obj = (MyStack*)malloc(sizeof(MyStack));
    assert(obj);
    QueueInit(&(obj->Q1));
    QueueInit(&(obj->Q2));
    return obj;
}

void myStackPush(MyStack* obj, int x) {
    if(!QueueEmpty(&(obj->Q1)))//push非空的,开始pushQ2
    QueuePush(&(obj->Q1),x);
    else
    QueuePush(&(obj->Q2),x);
}

bool myStackEmpty(MyStack* obj) {
    if(QueueEmpty(&(obj->Q1))&&QueueEmpty(&(obj->Q2)))
    return true;
    else
    return false;
}

int myStackPop(MyStack* obj) {
    if(myStackEmpty(obj))
    return -1;
    Queue* empty = &(obj->Q1);
    Queue* noempty = &(obj->Q2);//要改变Q1,Q2,用指针
    if(QueueEmpty(&(obj->Q2)))//假设法
    {
        empty = &(obj->Q2);
        noempty = &(obj->Q1);
    }

    while(QueueSize(noempty) != 1)
    {
        QueuePush(empty,QueueFront(noempty));
        QueuePop(noempty);
    }
    int x = QueueFront(noempty);
    QueuePop(noempty);
    return x;
}

int myStackTop(MyStack* obj) {
    if(myStackEmpty(obj))
    return -1;
    if(!QueueEmpty(&(obj->Q1)))
    return QueueBack(&(obj->Q1));
    else
    return QueueBack(&(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);
*/

4、设计循环队列

思路:

数组+%进行循环

objectivec 复制代码
typedef struct {
    int* arr;
    int front;
    int rear;
    int size;
    int capacity;
} MyCircularQueue;

MyCircularQueue* myCircularQueueCreate(int k) {
    MyCircularQueue* obj = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));
    obj->arr = (int*)malloc(sizeof(int)*k);
    obj->front = obj->rear = obj->size = 0;
    obj->capacity = k;
    return obj;
}

bool myCircularQueueIsEmpty(MyCircularQueue* obj) {
    if(obj->size == 0)
    return true;
    else
    return false;
}

bool myCircularQueueIsFull(MyCircularQueue* obj) {
    if(obj->front == obj->rear&&obj->size != 0)
    return true;
    else
    return false;
}

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

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

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

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

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

/**
 * Your MyCircularQueue struct will be instantiated and called as such:
 * MyCircularQueue* obj = myCircularQueueCreate(k);
 * bool param_1 = myCircularQueueEnQueue(obj, value);
 
 * bool param_2 = myCircularQueueDeQueue(obj);
 
 * int param_3 = myCircularQueueFront(obj);
 
 * int param_4 = myCircularQueueRear(obj);
 
 * bool param_5 = myCircularQueueIsEmpty(obj);
 
 * bool param_6 = myCircularQueueIsFull(obj);
 
 * myCircularQueueFree(obj);
*/
相关推荐
爱吃西瓜的小菜鸡7 分钟前
【C语言】判断回文
c语言·学习·算法
别NULL9 分钟前
机试题——疯长的草
数据结构·c++·算法
ZSYP-S2 小时前
Day 15:Spring 框架基础
java·开发语言·数据结构·后端·spring
唐叔在学习2 小时前
【唐叔学算法】第21天:超越比较-计数排序、桶排序与基数排序的Java实践及性能剖析
数据结构·算法·排序算法
ALISHENGYA2 小时前
全国青少年信息学奥林匹克竞赛(信奥赛)备考实战之分支结构(switch语句)
数据结构·算法
FeboReigns2 小时前
C++简明教程(文章要求学过一点C语言)(1)
c语言·开发语言·c++
FeboReigns2 小时前
C++简明教程(文章要求学过一点C语言)(2)
c语言·开发语言·c++
_小柏_3 小时前
C/C++基础知识复习(43)
c语言·开发语言·c++
yoyobravery3 小时前
c语言大一期末复习
c语言·开发语言·算法
武昌库里写JAVA5 小时前
浅谈怎样系统的准备前端面试
数据结构·vue.js·spring boot·算法·课程设计