8.栈和队列

一.栈

1.栈的概念及结构

2.栈的实现

这里我们使用数组作为我们的底层存储

a.Stack.h

cpp 复制代码
#pragma once

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

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

void STInit(ST* ps);
void STDestroy(ST* ps);


void STPush(ST* ps, STDataType x);
void STPop(ST* ps);
STDataType STTop(ST* ps);
int STSize(ST* ps);
bool STEmpty(ST* ps);

b.Stack.c

cpp 复制代码
#include"Stack.h"

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

	ps->a = NULL;
	ps->top = 0;
	ps->capacity = 0;
}

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

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

// ջ
// 11:55
void STPush(ST* ps, STDataType x)
{
	assert(ps);

	// ˣ 
	if (ps->top == ps->capacity)
	{
		int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
		STDataType* tmp = (STDataType*)realloc(ps->a, newcapacity * sizeof(STDataType));
		if (tmp == NULL)
		{
			perror("realloc fail");
			return;
		}

		ps->a = tmp;
		ps->capacity = newcapacity;
	}

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

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

	ps->top--;
}

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

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

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

	return ps->top;
}

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

	return ps->top == 0;
}

c.test.c

cpp 复制代码
#include"Stack.h"

int main()
{
	ST s;
	STInit(&s);
	STPush(&s, 1);
	STPush(&s, 2);
	STPush(&s, 3);

	int top = STTop(&s);
	printf("%d ", top);
	STPop(&s);

	top = STTop(&s);
	printf("%d ", top);
	STPop(&s);

	STPush(&s, 4);
	STPush(&s, 5);

	while (!STEmpty(&s))
	{
		int top = STTop(&s);
		printf("%d ", top);
		STPop(&s);
	}

	STDestroy(&s);

	return 0;
}

3.概念选择题

B

C

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

cpp 复制代码
class Solution {
public:
    bool isValid(string s) {
        stack<int> st;
        for (int i = 0; i < s.size(); i++) {
            if (s[i] == '(' || s[i] == '[' || s[i] == '{')
                st.push(i);
            else {
                if (st.empty())
                    return false;
                if (s[i] == ')' && s[st.top()] != '(')
                    return false;
                if (s[i] == '}' && s[st.top()] != '{')
                    return false;
                if (s[i] == ']' && s[st.top()] != '[')
                    return false;
                st.pop();
            }
        }
        return st.empty();
    }
};

二.队列

1.队列的概念及结构

2.队列的实现

所以,我们实现队列,采用单项不循环单链表(哨兵位,可要可不要)

a.Queue.h

cpp 复制代码
#pragma once
#include<stdlib.h>
#include<stdbool.h>
#include<assert.h>


typedef int QDataType;
typedef struct QueueNode
{
	int val;
	struct QueueNode* next;
}QNode;

//// 入队列
//void QueuePush(QNode** pphead, QNode** pptail);
//
//// 出队列
//void QueuePop(QNode** pphead, QNode** pptail);

typedef struct Queue
{
	QNode* phead;
	QNode* ptail;
	int size;
}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);
bool QueueEmpty(Queue* pq);
int QueueSize(Queue* pq);

b.Queue.c

cpp 复制代码
#include"Queue.h"

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

	pq->phead = NULL;
	pq->ptail = NULL;
	pq->size = 0;
}

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

	QNode* cur = pq->phead;
	while (cur)
	{
		QNode* next = cur->next;
		free(cur);

		cur = next;
	}

	pq->phead = pq->ptail = NULL;
	pq->size = 0;
}

// 入队列
void QueuePush(Queue* pq, QDataType x)
{
	assert(pq);
	QNode* newnode = (QNode*)malloc(sizeof(QNode));
	if (newnode == NULL)
	{
		perror("malloc fail");
		return;
	}

	newnode->val = x;
	newnode->next = NULL;

	if (pq->ptail)
	{
		pq->ptail->next = newnode;
		pq->ptail = newnode;
	}
	else
	{
		pq->phead = pq->ptail = newnode;
	}

	pq->size++;
}

// 出队列
void QueuePop(Queue* pq)
{
	assert(pq);

	// 0个节点
	// 温柔检查
	//if (pq->phead == NULL)
	//	return;
	
	// 暴力检查 
	assert(pq->phead != NULL);

	// 一个节点
	// 多个节点
	if (pq->phead->next == NULL)
	{
		free(pq->phead);
		pq->phead = pq->ptail = NULL;
	}
	else
	{
		QNode* next = pq->phead->next;
		free(pq->phead);
		pq->phead = next;
	}

	pq->size--;
}

QDataType QueueFront(Queue* pq)
{
	assert(pq);

	// 暴力检查 
	assert(pq->phead != NULL);

	return pq->phead->val;
}

QDataType QueueBack(Queue* pq)
{
	assert(pq);

	// 暴力检查 
	assert(pq->ptail != NULL);

	return pq->ptail->val;
}

bool QueueEmpty(Queue* pq)
{
	assert(pq);

	return pq->size == 0;
}

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

	return pq->size;
}

c.test.c

cpp 复制代码
#include"Queue.h"

int main()
{
	Queue q;
	QueueInit(&q);
	QueuePush(&q, 1);
	QueuePush(&q, 2);

	printf("%d ", QueueFront(&q));
	QueuePop(&q);

	QueuePush(&q, 3);
	QueuePush(&q, 4);

	while (!QueueEmpty(&q))
	{
		printf("%d ", QueueFront(&q));
		QueuePop(&q);
	}

	QueueDestroy(&q);

	return 0;
}

三.刷题(我们直接使用对应的C++中的已经实现好的栈和队列)

1.用队列实现栈

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

cpp 复制代码
class MyStack {
public:
    MyStack() {
        
    }
    
    void push(int x) {
        q_push.push(x);
        while(q_pop.size())
        {
            q_push.push(q_pop.front());
            q_pop.pop();
        }
        swap(q_push,q_pop);
    }
    
    int pop() {
        int ans = q_pop.front();
        q_pop.pop();
        return ans;
    }
    
    int top() {
        return q_pop.front();
    }
    
    bool empty() {
        return q_pop.size() == 0;
    }
    queue<int> q_pop;
    queue<int> q_push;
};

/**
 * Your MyStack object will be instantiated and called as such:
 * MyStack* obj = new MyStack();
 * obj->push(x);
 * int param_2 = obj->pop();
 * int param_3 = obj->top();
 * bool param_4 = obj->empty();
 */

2.用栈实现队列

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

cpp 复制代码
class MyQueue {
public:
    stack<int> popst,pushst;
    MyQueue() {
        
    }
    
    void push(int x) {
        pushst.push(x);
    }
    
    int pop() {
        if(popst.empty())
        {
            while(pushst.size())
            {
                popst.push(pushst.top());
                pushst.pop();
            }
        }
        int x = popst.top();
        popst.pop();
        return x;
    }
    
    int peek() {
        if(popst.size())
        {
            return popst.top();
        }
        while(pushst.size())
        {
            popst.push(pushst.top());
            pushst.pop();
        }
        return popst.top();
    }
    
    bool empty() {
        if(popst.empty() &&pushst.empty())
        {
            return true;
        }
        return false;
    }
};

/**
 * Your MyQueue object will be instantiated and called as such:
 * MyQueue* obj = new MyQueue();
 * obj->push(x);
 * int param_2 = obj->pop();
 * int param_3 = obj->peek();
 * bool param_4 = obj->empty();
 */

3.设计循环队列

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

cpp 复制代码
class MyCircularQueue {
private:
    int front;
    int end;
    int capacity;
    vector<int> elements;
public:
    MyCircularQueue(int k) {
        capacity = k + 1;
        elements = vector<int>(k + 1);
        front = end = 0;
    }
    
    bool enQueue(int value) {
        if (isFull()) {
            return false;
        }
        elements[end] = value;
        end = (end + 1) % capacity;
        return true;
    }
    
    bool deQueue() {
        if (isEmpty()) {
            return false;
        }
        front = (front + 1) % capacity;
        return true;
    }
    
    int Front() {
        if (isEmpty()) {
            return -1;
        }
        return elements[front];
    }
    
    int Rear() {
        if(isEmpty())
        {
            return -1;
        }
        return elements[(end - 1 + capacity) % capacity];
    }
    
    bool isEmpty() {
        return end == front;
    }
    
    bool isFull() {
        return (end + 1) % capacity == front;
    }
};

/**
 * Your MyCircularQueue object will be instantiated and called as such:
 * MyCircularQueue* obj = new MyCircularQueue(k);
 * bool param_1 = obj->enQueue(value);
 * bool param_2 = obj->deQueue();
 * int param_3 = obj->Front();
 * int param_4 = obj->Rear();
 * bool param_5 = obj->isEmpty();
 * bool param_6 = obj->isFull();
 */
相关推荐
报错小能手4 分钟前
数据结构 字典树
开发语言·数据结构
XLYcmy13 分钟前
高级密码生成器程序详解:专门设计用于生成基于用户个人信息的密码猜测组合
开发语言·数据结构·python·网络安全·数据安全·源代码·口令安全
AI科技星20 分钟前
时空的固有脉动:波动方程 ∇²L = (1/c²) ∂²L/∂t² 的第一性原理推导、诠释与验证
数据结构·人工智能·算法·机器学习·重构
独自破碎E21 分钟前
Leetcode862和至少为K的最短子数组
java·开发语言
qq_3707730924 分钟前
x64dbg 脚本常用命令
开发语言·x64dbg
阿豪只会阿巴28 分钟前
【多喝热水系列】从零开始的ROS2之旅——Day4
c++·笔记·python·ros2
军军君0135 分钟前
Three.js基础功能学习五:雾与渲染目标
开发语言·前端·javascript·学习·3d·前端框架·three
charlie11451419141 分钟前
FreeRTOS:软件定时器(Software Timers)与时间管理
开发语言·笔记·学习·freertos·实时操作系统·工程
2401_8414956443 分钟前
【LeetCode刷题】寻找重复数
数据结构·python·算法·leetcode·链表·数组·重复数
washingtin1 小时前
Get “https://registry-1.docker.io/v2/“: context deadline exceeded
java·开发语言