Data structure - stack and queue OJ questions

Insert image description here


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
Insert image description here
Insert image description here

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:
Insert image description here
Insert image description here
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
Insert image description here
Insert image description here

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
Insert image description here
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
Insert image description here
Insert image description here

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:
Insert image description here
Insert image description here
Insert image description here
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!

Guess you like

Origin blog.csdn.net/mdjsmg/article/details/132467398