【数据结构 C语言版】第六篇 栈、队列经典必刷面试考研题
写在前面
更新情况记录:
最近更新时间 | 更新次数 |
---|---|
2022/10/20 | 1 |
参考博客与书籍以及链接:
(非常感谢这些博主们的文章,将我的一些疑问得到解决。)
参考博客链接或书籍名称 |
---|
《数据结构》陈越 |
代码随想录 |
总目录:目前数据结构文章太少,没有写。 |
正文
0.食用说明
本章题目来源:牛客、力扣(其他平台未完待续)
假如你现在不知道栈或者队列怎么实现,那么不妨看看我的博客:
1.栈与队列的必刷题
1.1 括号匹配问题
【题目描述】
题目链接:20. 有效的括号
【题目解读】
1.基本思路:
取到括号就进栈,取到右扩号与前一个进栈的进行比较,如果符合就出栈否则就是不匹配,返回false。
最后在判断栈是否为空。
形象的比喻:
将这个字符串从左往右写,一旦遇到匹配上的括号,就把这对括号擦掉,就像“消消乐”一样!
2.关于不符合情况的思考
(1)如果都是左括号,形如“(( ”,根本不出栈,那么就需要最后判断是否为空。
(2)假如直接是空的字符串或者只有右括号,形如:“}”或者“ ”,那么得判断栈是否为空。
3.图解(最重要的一步):
【题目代码】
既然是c语言写的,嘿嘿,那必须得自己实现一个栈啊。
栈的部分:
//自己造一个栈吧
typedef int DataType;
typedef struct Stack
{
DataType* a;
int top;
int capacity;
}Stack;
//初始化
void StackInit(Stack* ps)
{
assert(ps);
ps->a=NULL;
ps->top=ps->capacity=0;
}
//进栈
void StackPush(Stack* ps,DataType x)
{
assert(ps);
if(ps->top==ps->capacity)
{
int newCapacity=ps->capacity==0?4:ps->capacity*2;
DataType* tmp=(DataType*)realloc(ps->a,newCapacity*sizeof(DataType));
ps->a=tmp;
ps->capacity=newCapacity;
}
ps->a[ps->top]=x;
ps->top++;
}
//出栈
void StackPop(Stack* ps)
{
assert(ps);
ps->top--;
}
//栈空判断
bool StackEmpty(Stack* ps)
{
assert(ps);
//注意别忘记加==0
//top为0就说明没有值
return ps->top==0;
}
//栈销毁
void StackDestroy(Stack* ps)
{
assert(ps);
free(ps->a);
ps->top=ps->capacity=0;
}
解题的部分:
bool isValid(char * s){
Stack stack;
StackInit(&stack);
while(*s)
{
//取到左括号
if(*s=='('
||*s=='['
||*s=='{')
{
StackPush(&stack,*s);
}
//取到右括号
else
{
//前面是空不匹配
if(StackEmpty(&stack))
{
return false;
}
//前面不为空进行比较
else
{
char top=stack.a[stack.top-1];//取栈顶元素
StackPop(&stack);
if(!((*s=='}'&&top=='{')
||(*s==']'&&top=='[')
||(*s==')'&&top=='(')))
{
return false;
}
}
}
++s;
}
//判断栈里面是否为空
bool flag=StackEmpty(&stack);
StackDestroy(&stack);
return flag;
}
爽不?那就试着用c++刷题,不会?那么看我的博客吧。
C++博客:点击跳转
1.2 用队列实现栈
【题目描述】
题目链接:225. 用队列实现栈 - 力扣(LeetCode)
【题目解读】
1.如何用队列实现栈?
(1)文字描述:我们可以用两个队列实现栈的功能。
(假设有队列A与队列B)
a.
假设先push 1,2,3,4
队列A:1,2,3,4
队列B:空
然后再pop 4,但是队列A只能先进先出,无法出4,那么我们可以把1,2,3放进队列B中
队列A pop1,队列B push1
队列A:2,3,4
队列B:1
队列A pop 2 ,队列B push 2
队列A:3,4
队列B:1,2
队列A pop 3,队列B push 3
队列A:4
队列B:1,2,3
队列A pop 4,实现栈的功能。
队列A:空
队列B:1,2,3
b.
假如说想要继续pop 3
那么把队列B中的1,2导入队列A中。
队列B pop 3就好了。
2.题目要求的分析:
void push (int x)
作用:将元素x压入栈顶。
步骤:在有数据元素的那个队列中进行入队列操作即可。
int pop()
作用:移除并返回栈顶元素
步骤:有数据元素的那个队列把队尾元素前的数据元素全部导入另一个队列(就是上面pop 4的过程),然后pop 队尾元素(也就是逻辑上的栈顶元素)。
int top()
作用:返回栈顶元素
步骤:返回有数据元素的队列的队尾就好了。
bool empty()
作用:如果栈是空的,返回true;否则,返回false。
步骤:两个队列都没元素说明真没元素了。
【题目代码】
队列的代码
typedef int QDataType;
typedef struct QListNode
{
struct QListNode* next;
QDataType data;
}QNode;
typedef struct Queue
{
QNode* front;
QNode* rear;
}Queue;
void QueueInit(Queue* q)
{
assert(q);
q->front = q->rear = NULL;
}
void QueuePush(Queue* q, QDataType data)
{
assert(q);
QNode* newnode = (QNode*)malloc(sizeof(QNode));
newnode->data = data;
newnode->next = NULL;
if (q->rear == NULL&&q->front==NULL)
{
q->front = q->rear = newnode;
}
else
{
q->rear->next = newnode;
q->rear = newnode;
}
printf("QueuePush\n");
}
bool QueueEmpty(Queue* q)
{
assert(q);
return (q->front == NULL && q->rear == NULL);
}
void QueuePop(Queue* q)
{
assert(q);
assert(!QueueEmpty(q));
if (q->front->next == NULL)
{
free(q->rear);
q->rear = q->front = NULL;
}
else
{
QNode* del = q->front;
q->front = del->next;
free(del);
del = NULL;
}
}
void QueueDestroy(Queue* q)
{
assert(q);
QNode* cur = q->front;
while (cur)
{
QNode* del = cur;
cur = cur->next;
free(del);
}
q->front = q->rear = NULL;
}
int QueueSize(Queue* q)
{
assert(q);
if (QueueEmpty(q))
{
return 0;
}
else
{
QNode* cur = q->front;
int count = 0;
while (cur)
{
cur = cur->next;
count++;
}
return count;
}
}
QDataType QueueFront(Queue* q)
{
assert(q);
assert(!QueueEmpty(q));
return q->front->data;
}
QDataType QueueBack(Queue* q)
{
assert(q);
assert(!QueueEmpty(q));
return q->rear->data;
}
题解的代码
typedef struct {
Queue q1;
Queue q2;
} MyStack;
MyStack* myStackCreate() {
MyStack* obj = (MyStack*)malloc(sizeof(MyStack));
QueueInit(&obj->q1);
QueueInit(&obj->q2);
return obj;
}
void myStackPush(MyStack* obj, int x) {
if (QueueEmpty(&obj->q1)==NULL)
{
QueuePush(&obj->q1, x);
}
else
{
QueuePush(&obj->q2, x);
}
}
int myStackPop(MyStack* obj) {
Queue* empty = &obj->q1;
Queue* noneEmpty = &obj->q2;
if (!QueueEmpty(&obj->q1))
{
empty = &obj->q2;
noneEmpty = &obj->q1;
}
while (QueueSize(noneEmpty) > 1)
{
QueuePush(empty, QueueFront(noneEmpty));
QueuePop(noneEmpty);
}
int top = QueueFront(noneEmpty);
QueuePop(noneEmpty);
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);
obj = NULL;
}
1.3 用栈实现队列
【题目描述】
【题目解读】
【题目代码】
1.4 设计循环队列
【题目描述】
【题目解读】
【题目代码】
2.未完待续
今天有点忙,先写两题,剩下的两题我一定会在星期五结束之前写好。
文章未完待续…