Small improvements to stack and queue!
- Preface
- 1. Use queues to implement stacks
- 2. Use stack to implement queue
- 3. Design circular queue
-
- (1) Interface definition of circular queue
- (2) Initialization of circular queue
- (3) Definition of null function
- (4) Definition of full function
- (5) Definition of circular queue insertion function
- (6) Definition of circular queue deletion function
- (7) Find the definition of the team head function
- (8) Find the definition of the tail function
- (9) Definition of destruction function
- Summarize
Preface
Welcome to the special improvement class!
Today’s question is a little more difficult!
But as long as you put your heart into it, it won’t be a problem for the students!
1. Use queues to implement stacks
Question link: OJ link
Tips:
1 <= x <= 9;
push, pop, top and empty can be called up to 100 times;
each time pop and top are called, the stack is guaranteed not to be empty;
Core idea:
Use a queue to simulate the first-in-last-out feature of popping a stack!
Problem-solving ideas:
This problem can use two queues to implement a stack, and always keep one queue empty each time. The
push operation is equivalent to the enqueuing operation of the non-empty queue, and
the popping operation is equivalent to the tail element of the non-empty queue. Dequeue. At this time, you need to enqueue the remaining elements of the non-empty queue except the last element into the empty queue, and then dequeue the last element at the end of the queue.
Legend analysis:
code example:
Queue interface implementation
First import the implementation interface of the queue
This involves the content of the previous queue creation!
If you don’t understand, you can check it out: Stack and Queue
//头文件的声明
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>
//链表接口定义
typedef int QDataType;
typedef struct QueueNode
{
struct QueueNode* next;
QDataType data;
}QNode;
//队列接口定义
typedef struct Queue
{
QNode* head;
QNode* tail;
int size;
}Que;
//队列初始化
void QueueInit(Que* pq);
//队列销毁
void QueueDestroy(Que* pq);
//插入
void QueuePush(Que* pq, QDataType x);
//删除
void QueuePop(Que* pq);
//查找队头元素
QDataType QueueFront(Que* pq);
//查找队尾元素
QDataType QueueBack(Que* pq);
//判断是否为空
bool QueueEmpty(Que* pq);
//计算长度
int QueueSize(Que* pq);
void QueueInit(Que* pq)
{
assert(pq);
pq->head = pq->tail = NULL;
pq->size = 0;
}
void QueueDestroy(Que* pq)
{
assert(pq);
QNode* cur = pq->head;
while (cur)
{
QNode* next = cur->next;
free(cur);
cur = next;
}
pq->head = pq->tail = NULL;
pq->size = 0;
}
void QueuePush(Que* pq, QDataType x)
{
assert(pq);
QNode* newnode = (QNode*)malloc(sizeof(QNode));
if (newnode == NULL)
{
perror("malloc fail");
exit(-1);
}
newnode->data = x;
newnode->next = NULL;
if (pq->tail == NULL)
{
pq->head = pq->tail = newnode;
}
else
{
pq->tail->next = newnode;
pq->tail = newnode;
}
pq->size++;
}
void QueuePop(Que* pq)
{
assert(pq);//判断队列指针指向是否为空
assert(!QueueEmpty(pq));//判断队列里面的数据是否为空
if (pq->head->next == NULL)
{
free(pq->head);
pq->head = pq->tail = NULL;
}
else
{
QNode* next = pq->head->next;
free(pq->head);
pq->head = next;
}
pq->size--;
}
//查找队头元素
QDataType QueueFront(Que* pq)
{
assert(pq);
assert(!QueueEmpty(pq));
return pq->head->data;
}
//查找队尾元素
QDataType QueueBack(Que* pq)
{
assert(pq);
assert(!QueueEmpty(pq));
return pq->tail->data;
}
//判断是否为空
bool QueueEmpty(Que* pq)
{
assert(pq);
return pq->head == NULL;
}
//长度计算
int QueueSize(Que* pq)
{
assert(pq);
return pq->size;
}
Definition of functional functions of queue implementation stack
(1) Stack interface definition
typedef struct {
Que q1;
Que q2;
} MyStack;
(2) Initialization of stack
MyStack* myStackCreate() {
MyStack*pst = (MyStack*)malloc(sizeof(MyStack));
QueueInit(&pst->q1);
QueueInit(&pst->q2);
return pst;
}
(3) Definition of push function
void myStackPush(MyStack* obj, int x) {
if(!QueueEmpty(&obj->q1)){
QueuePush(&obj->q1,x);
}
else{
QueuePush(&obj->q2,x);
}
}
(4) Definition of pop function
int myStackPop(MyStack* obj) {
Que*Empty=&obj->q1;
Que*nonEmpty=&obj->q2;
if(!QueueEmpty(&obj->q1)){
Empty=&obj->q2;
nonEmpty=&obj->q1;
}
while(QueueSize(nonEmpty)>1){
QueuePush(Empty,QueueFront(nonEmpty));
QueuePop(nonEmpty);
}
int top = QueueFront(nonEmpty);
QueuePop(nonEmpty);
return top;
}
(5) Find the top element of the stack
int myStackTop(MyStack* obj) {
if(!QueueEmpty(&obj->q1)){
return QueueBack(&obj->q1);
}
else{
return QueueBack(&obj->q2);
}
}
(6) Definition of null function
bool myStackEmpty(MyStack* obj) {
return QueueEmpty(&obj->q1)&&QueueEmpty(&obj->q2);
}
(7) Definition of destruction function
void myStackFree(MyStack* obj) {
QueueDestroy(&obj->q1);
QueueDestroy(&obj->q2);
free(obj);
}
2. Use stack to implement queue
Question link: OJ link
Tip:
1 <= x <= 9
A maximum of 100 calls to push, pop, peek, and empty
assuming all operations are valid (for example, an empty queue will not call pop or peek operations)
Core idea:
Use the stack to simulate the first-in-first-out feature of the queue!
Problem-solving ideas:
This problem can be solved with two stacks. One stack performs the enqueuing operation, and the other stack performs the dequeuing operation. The dequeuing
operation: When the dequeuing stack is not empty, the dequeuing operation is performed directly. If it is empty, the dequeuing operation is performed directly. , you need to import all the stack elements that are enqueued into the stack that is dequeued, and then perform the pop-out operation.
Legend parsing
code example:
Stack interface implementation
First import the implementation interface of the stack
This involves the establishment of the previous stack!
If you don’t understand, you can check it out: Stack and Queue
//栈的接口定义
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);
//初始化
void STInit(ST* ps)
{
assert(ps);
ps->a = NULL;
ps->capacity = 0;
ps->top = 0;
}
//销毁
void STDestroy(ST* ps)
{
assert(ps);
free(ps->a);
ps->a = NULL;
ps->top = ps->capacity = 0;
}
//插入
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, sizeof(STDataType) * newCapacity);
if (tmp == NULL)
{
perror("realloc fail");
exit(-1);
}
ps->a = tmp;
ps->capacity = newCapacity;
}
ps->a[ps->top] = x;
ps->top++;
}
//删除栈顶元素
void STPop(ST* ps)
{
assert(ps);
assert(ps->top > 0);
--ps->top;
}
//查找栈顶元素
STDataType STTop(ST* ps)
{
assert(ps);
assert(ps->top > 0);
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;
}
Definition of functional functions of stack implementation queue
(1) Queue interface definition
typedef struct {
ST pushst;
ST popst;
} MyQueue;
(2) Initialization of queue
MyQueue* myQueueCreate() {
MyQueue*obj = (MyQueue*)malloc(sizeof(MyQueue));
STInit(&obj->pushst);
STInit(&obj->popst);
return obj;
}
(3) Definition of enqueue function
void myQueuePush(MyQueue* obj, int x) {
STPush(&obj->pushst,x);
}
(4) Definition of dequeue function
int myQueuePop(MyQueue* obj) {
int front = myQueuePeek(obj);
STPop(&obj->popst);
return front;
}
(5) Find the definition of the team head function
int myQueuePeek(MyQueue* obj) {
if(STEmpty(&obj->popst))
{
while(!STEmpty(&obj->pushst)){
STPush(&obj->popst,STTop(&obj->pushst));
STPop(&obj->pushst);
}
}
return STTop(&obj->popst);
}
(6) Definition of null function
bool myQueueEmpty(MyQueue* obj) {
return STEmpty(&obj->popst)&&STEmpty(&obj->pushst);
}
(7) Definition of destruction function
void myQueueFree(MyQueue* obj) {
STDestroy(&obj->popst);
STDestroy(&obj->pushst);
free(obj);
}
3. Design circular queue
Question link: OJ link
Tip:
All values will be in the range 0 to 1000;
operands will be in the range 1 to 1000;
please do not use the built-in queue library.
Core idea:
A loop connected end to end is a ring!
Problem-solving idea:
Implement circular queue
enqueue : first determine whether the queue is full, and then perform the enqueue operation. The enqueue operation needs to consider the index loop problem. When the index is out of bounds, it needs to be minimized. Value
Dequeue: First, you must determine whether the queue is empty, and then perform the dequeue operation. Dequeue also needs to consider the issue of index loop. Empty judgment
: Queue head == Queue tail.
Full judgment: Queue tail + 1 == Queue head.
Legend analysis:
code example:
(1) Interface definition of circular queue
typedef struct {
int *a;
int front;
int rear;
int k;
} MyCircularQueue;
(2) Initialization of circular queue
MyCircularQueue* myCircularQueueCreate(int k) {
MyCircularQueue*obj=(MyCircularQueue*)malloc(sizeof(MyCircularQueue));
obj->a=(int*)malloc(sizeof(int)*(k+1));
obj->front=obj->rear=0;
obj->k=k;
return obj;
}
(3) Definition of null function
bool myCircularQueueIsEmpty(MyCircularQueue* obj) {
return obj->front==obj->rear;
}
(4) Definition of full function
bool myCircularQueueIsFull(MyCircularQueue* obj) {
return (obj->rear+1)%(obj->k+1)==obj->front;
}
(5) Definition of circular queue insertion function
bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {
if(myCircularQueueIsFull(obj))
return false;
obj->a[obj->rear]=value;
obj->rear++;
obj->rear%=(obj->k+1);
return true;
}
(6) Definition of circular queue deletion function
bool myCircularQueueDeQueue(MyCircularQueue* obj) {
if(myCircularQueueIsEmpty(obj))
return false;
++obj->front;
obj->front%=(obj->k+1);
return true;
}
(7) Find the definition of the team head function
int myCircularQueueFront(MyCircularQueue* obj) {
if(myCircularQueueIsEmpty(obj))
return -1;
else
return obj->a[obj->front];
}
(8) Find the definition of the tail function
int myCircularQueueRear(MyCircularQueue* obj) {
if(myCircularQueueIsEmpty(obj))
return -1;
else
return obj->a[(obj->rear+obj->k)%(obj->k+1)];
}
(9) Definition of destruction function
void myCircularQueueFree(MyCircularQueue* obj) {
free(obj->a);
free(obj);
}
Summarize
Today’s question is really difficult!
But also believe in yourself!
Confidence is the best way to solve problems!