前言
前面的博客写了如何实现栈和队列,下来我们来看一下队列和栈的相关习题。
链接: 栈和队列的实现
 
文章目录
- 前言
 - 1.用栈实现括号匹配
 - 2.用队列实现栈
 - 3.用栈实现队列
 - 4.设计循环队列
 
1.用栈实现括号匹配

此题最重要的就是数量匹配和顺序匹配。
用栈可以完美的做到:
1.左括号入栈
2.有右括号,取栈顶左括号匹配

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include<stdbool.h>
typedef char STDataType;
typedef struct Stack
{
	STDataType* a;
	int top;		// 标识栈顶位置的
	int capacity;
}ST;
void STInit(ST* pst);
void STDestroy(ST* pst);
// 栈顶插入删除
void STPush(ST* pst, STDataType x);
void STPop(ST* pst);
STDataType STTop(ST* pst);
bool STEmpty(ST* pst);
int STSize(ST* pst);
void STInit(ST* pst)
{
	assert(pst);
	pst->a = NULL;
	pst->capacity = 0;
	// 表示top指向栈顶元素的下一个位置
	pst->top = 0;
	// 表示top指向栈顶元素
//pst->top = -1;
}
void STDestroy(ST* pst)
{
	assert(pst);
	free(pst->a);
	pst->a = NULL;
	pst->top = pst->capacity = 0;
}
// 栈顶插入删除
void STPush(ST* pst, STDataType x)
{
	assert(pst);
	if (pst->top == pst->capacity)
	{
		int newcapacity = pst->capacity == 0 ? 4 : pst->capacity * 2;
		STDataType* tmp = (STDataType*)realloc(pst->a, sizeof(STDataType) * newcapacity);
		if (tmp == NULL)
		{
			perror("realloc fail");
			return;
		}
		pst->a = tmp;
		pst->capacity = newcapacity;
	}
	pst->a[pst->top] = x;
	pst->top++;
}
void STPop(ST* pst)
{
	assert(pst);
	// 不为空
	assert(pst->top > 0);
	pst->top--;
}
STDataType STTop(ST* pst)
{
	assert(pst);
	// 不为空
	assert(pst->top > 0);
	return pst->a[pst->top - 1];
}
bool STEmpty(ST* pst)
{
	assert(pst);
	/*if (pst->top == 0)
	{
		return true;
	}
	else
	{
		return false;
	}*/
	return pst->top == 0;
}
int STSize(ST* pst)
{
	assert(pst);
	return pst->top;
}
//这里以上都是栈的代码
bool isValid(char* s)
{
	ST st;
	STInit(&st);
	while (*s)
	{
		if (*s == '[' || *s == '(' || *s == '{')
		{
			STPush(&st, *s);
		}
		else
		{
			if (STEmpty(&st)!=NULL)//右括号比左括号多
			{
				STDestroy(&st);
				return false;
			}
			char top = STTop(&st);
			STPop(&st);
			if ((*s == ']' && top != '[')//控制顺序不匹配
				|| (*s == '}' && top != '{')
				|| (*s == ')' && top != '('))
			{
				STDestroy(&st);
				return false;
			}
		}
		++s;
	}
	bool ret = STEmpty(&st);//如果栈空了,那么就是都匹配走了
	STDestroy(&st);         //只要不空,说明没匹配完,但只能解决左括号多,右括号少的问题
	return ret;
}
 
2.用队列实现栈


 
 这样感觉没什么用,很低效,但是这题考的就是我们对于队列和栈性质的理解!
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include<stdbool.h>
typedef int QDataType;
typedef struct QueueNode
{
	QDataType val;
	struct QueueNode* next;
}QNode;
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);
void QueueInit(Queue* pq)
{
	assert(pq);
	pq->phead = 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 == NULL)
	{
		pq->ptail = pq->phead = newnode;
	}
	else
	{
		pq->ptail->next = newnode;
		pq->ptail = newnode;
	}
	pq->size++;
}
void QueuePop(Queue* pq)
{
	assert(pq);
	// 
	assert(pq->phead);
	QNode* del = pq->phead;
	pq->phead = pq->phead->next;
	free(del);
	del = NULL;
	if (pq->phead == NULL)
		pq->ptail = NULL;
	pq->size--;
}
QDataType QueueFront(Queue* pq)
{
	assert(pq);
	// 
	assert(pq->phead);
	return pq->phead->val;
}
QDataType QueueBack(Queue* pq)
{
	assert(pq);
	// 
	assert(pq->ptail);
	return pq->ptail->val;
}
bool QueueEmpty(Queue* pq)
{
	assert(pq);
	return pq->phead == NULL;
}
int QueueSize(Queue* pq)
{
	assert(pq);
	return pq->size;
}
//这里之前都是队列的代码
typedef struct //匿名结构体
{
	Queue q1;
	Queue q2;
} MyStack;
MyStack* myStackCreate() 
{
	MyStack* pst = (MyStack*)malloc(sizeof(MyStack));
	QueueInit(&pst->q1);
	QueueInit(&pst->q2);
	return pst;
}
void myStackPush(MyStack* obj, int x) //插入,哪个不为空就往哪里插,都为空随便进一个都行
{
	if (!QueueEmpty(&obj->q1))
		QueuePush(&obj->q1, x);
	else
		QueuePush(&obj->q2, x);
}
int myStackPop(MyStack* obj) 
{
	//假设q1为空,q2不为空
    Queue* emptyq=&obj->q1;
    Queue* nonemptyq=&obj->q2;
	if (!QueueEmpty(&obj->q1))//如果假设错了,就交换
	{
		emptyq = &obj->q2;
		nonemptyq = &obj->q1;   
	}
	//非空队列钱N-1个元素导入空队列,最后一个就是栈顶元素
	while (QueueSize(nonemptyq)>1)
	{
		QueuePush(emptyq, QueueFront(nonemptyq));//将非空队列插入空队列
		QueuePop(nonemptyq);//删掉
	}
	//并返回栈顶元素
	int top=QueueFront(nonemptyq);
    QueuePop(nonemptyq);
    return top;
}
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);
}
 
3.用栈实现队列

 
 
和队列实现栈的思路一样,主要考察栈和队列的性质
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include<stdbool.h>
typedef int STDataType;
typedef struct Stack
{
	STDataType* a;
	int top;		// 标识栈顶位置的
	int capacity;
}ST;
void STInit(ST* pst);
void STDestroy(ST* pst);
// 栈顶插入删除
void STPush(ST* pst, STDataType x);
void STPop(ST* pst);
STDataType STTop(ST* pst);
bool STEmpty(ST* pst);
int STSize(ST* pst);
void STInit(ST* pst)
{
	assert(pst);
	pst->a = NULL;
	pst->capacity = 0;
	// 表示top指向栈顶元素的下一个位置
	pst->top = 0;
	// 表示top指向栈顶元素
	//pst->top = -1;
}
void STDestroy(ST* pst)
{
	assert(pst);
	free(pst->a);
	pst->a = NULL;
	pst->top = pst->capacity = 0;
}
// 栈顶插入删除
void STPush(ST* pst, STDataType x)
{
	assert(pst);
	if (pst->top == pst->capacity)
	{
		int newcapacity = pst->capacity == 0 ? 4 : pst->capacity * 2;
		STDataType* tmp = (STDataType*)realloc(pst->a, sizeof(STDataType) * newcapacity);
		if (tmp == NULL)
		{
			perror("realloc fail");
			return;
		}
		pst->a = tmp;
		pst->capacity = newcapacity;
	}
	pst->a[pst->top] = x;
	pst->top++;
}
void STPop(ST* pst)
{
	assert(pst);
	// 不为空
	assert(pst->top > 0);
	pst->top--;
}
STDataType STTop(ST* pst)
{
	assert(pst);
	// 不为空
	assert(pst->top > 0);
	return pst->a[pst->top - 1];
}
bool STEmpty(ST* pst)
{
	assert(pst);
	/*if (pst->top == 0)
	{
		return true;
	}
	else
	{
		return false;
	}*/
	return pst->top == 0;
}
int STSize(ST* pst)
{
	assert(pst);
	return pst->top;
}
//以上为栈的代码
typedef struct 
{
	ST pushst;//入数据栈
	ST popst;//出数据栈
} MyQueue;
MyQueue* myQueueCreate() 
{
	MyQueue* obj = (MyQueue*)malloc(sizeof(MyQueue));
	STInit(&obj->popst);
	STInit(&obj->pushst);
	return obj;
}
void myQueuePush(MyQueue* obj, int x) 
{
	STPush(&obj->pushst, x);
}
int myQueuePop(MyQueue* obj)
{
	int front = myQueuePeek(obj);//有数据不动,没数据导数据
	STPop(&obj->popst);
	return front;
}
int myQueuePeek(MyQueue* obj) //返回队列开头的元素
{
	if (STEmpty(&obj->popst))//如果popst不为空,跳到最后返回栈顶元素
	{                        
		while (!STEmpty(&obj->pushst))
		{//popst为空,那就导数据,把pushst的数据导入popst,再返回栈顶元素
			STPush(&obj->popst, STTop(&obj->pushst));
			STPop(&obj->pushst);
		}
	}
	return STTop(&obj->popst);//返回栈顶元素
}
bool myQueueEmpty(MyQueue* obj) 
{
	return STEmpty(&obj->popst) && STEmpty(&obj->pushst);
}
void myQueueFree(MyQueue* obj) 
{
	STDestroy(&obj->popst);
	STDestroy(&obj->pushst);
	free(obj);
}
 
部分函数的结构如下:
 
4.设计循环队列

 
 ①
 
 ②
 
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdbool.h>
typedef struct
{
    int* a;//数组指针(一开始开的空间)
    int front;//头
    int back;//尾
    int k;//数据个数
} MyCircularQueue;
MyCircularQueue* myCircularQueueCreate(int k)
{
    MyCircularQueue* obj = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));
    obj->a = (int*)malloc(sizeof(int) * (k + 1));
    obj->front = 0;
    obj->back = 0;
    obj->k = k;
    return obj;
}
bool myCircularQueueIsEmpty(MyCircularQueue* obj)
{
    return obj->front == obj->back;//头等于尾是空
}
bool myCircularQueueIsFull(MyCircularQueue* obj)
{
    return (obj->back + 1) % (obj->k + 1) == obj->front;//上述图片分析出的公式
}
bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) //插入
{
    if (myCircularQueueIsFull(obj))
        return false;              //如果满了就返回错
    obj->a[obj->back] = value;
    obj->back++;
    obj->back %= (obj->k + 1);//防止越界
    return true;
}
bool myCircularQueueDeQueue(MyCircularQueue* obj) //删除
{
    if (myCircularQueueIsEmpty(obj))
        return false;
    ++obj->front;
    obj->front %= (obj->k + 1);
    return true;
}
int myCircularQueueFront(MyCircularQueue* obj) //从队首获取元素。如果队列为空,返回 -1 。
{
    if (myCircularQueueIsEmpty(obj))
        return -1;
    return obj->a[obj->front];
}
int myCircularQueueRear(MyCircularQueue* obj) //获取队尾元素。如果队列为空,返回 -1 。
{
    if (myCircularQueueIsEmpty(obj))
        return -1;
    if (obj->back == 0)
        return obj->a[obj->k];
    else
        return obj->a[obj->back - 1];
}
void myCircularQueueFree(MyCircularQueue* obj)
{
    free(obj->a);
    free(obj);
}
 
部分代码结构如下:
 ①
 
 ②
 
 ③
 






![14.Tomcat和HTTP协议-[一篇通]](img/doge.jpg)
![【算法每日一练]-图论(保姆级教程篇7 最小生成树 ,并查集模板篇)#村村通 #最小生成树](https://img-blog.csdnimg.cn/38766dc5397244fcb073357178b58f4b.png)



![[Linux] Linux入门必备的基本指令(不全你打我)](https://img-blog.csdnimg.cn/0ad0176b34a947d6b015fbe0e97ac00d.png)







