Mutual realization of queue and stack (2)

This article uses two stacks to implement queues

content

Implementing queues with stacks

Writing the stack

Implementation Analysis of Queue

Queue definition and initialization

 enqueue (push)

dequeue (pop)

Returns the head element of the queue

Determine whether the queue is empty and the destruction of the queue


Question link: 232. Implementing Queues with Stacks - LeetCode (leetcode-cn.com)


Implementing queues with stacks

Implement a FIFO queue with two LIFO stacks.

Push 1 2 3 4 5

Pop 1 2 3 4 5

Writing the stack

The stack has the property of last-in-first-out. You can operate on the top of the stack. We use the sequence table to implement the stack. It has been implemented before, and we directly add the code:

typedef int Datatype;

typedef struct Stack
{
	Datatype* a;
	int top;   //栈顶位置
	int capacity;   //容量
}ST;

void StackInit(ST* ps);

void StackDestory(ST* ps);

void StackPush(ST* ps,Datatype x);

void StackPop(ST* ps);

//判断栈是否为空
bool StackEmpty(ST* ps);

//数据个数
int StackSize(ST* ps);

//访问栈顶数据
Datatype StackTop(ST* ps);


//初始化
void StackInit(ST* ps)
{
	assert(ps);
	ps->a = NULL;
	ps->capacity = 0;
	ps->top = 0;
}

//销毁
void StackDestory(ST* ps)
{
	assert(ps);
	free(ps->a);
	ps->a = NULL;
	ps->capacity = ps->top = 0;
}

void StackPush(ST* ps, Datatype x)
{
	assert(ps);
	if (ps->top == ps->capacity)
	{
		int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
		ps->a = realloc(ps->a, newcapacity*sizeof(Datatype));
		if (ps->a == NULL)
		{
			printf("realloc fail\n");
			exit(-1);
		}
		ps->capacity = newcapacity;
	}
	ps->a[ps->top] = x;
	ps->top++;
}

void StackPop(ST* ps)
{
	assert(ps);
	assert(ps->top>0);
	ps->top--;
}

//判断栈是否为空
bool StackEmpty(ST* ps)
{
	assert(ps);
	//if (ps->top > 0)
	//{
	//	return false;
	//}
	//else
	//{
	//	return true;
	//}
	return ps->top == 0;
}

//数据个数
int StackSize(ST* ps)
{
	assert(ps);
	return ps->top;
}

//访问栈顶数据
Datatype StackTop(ST* ps)
{
	assert(ps);
	assert(ps->top>0);
	return ps->a[ps->top-1];
}

Implementation Analysis of Queue

Two stacks implement queues, and two LIFO stacks are used to implement FIFO for a set of data.

Diagram:

Queue definition and initialization

It is still to open up space, determine whether it is successful, and then initialize the two stacks in the queue.

typedef struct {
    ST Pushs1;
    ST Pops2;
} MyQueue;


MyQueue* myQueueCreate() {
    MyQueue* obj=(MyQueue*)malloc(sizeof(MyQueue));
    assert(obj);
    StackInit(&obj->Pushs1);
    StackInit(&obj->Pops2);
    return obj;
}

 enqueue (push)

The stack is initialized, it has been empty, and it can be directly pushed into the stack

void myQueuePush(MyQueue* obj, int x) {
    assert(obj);
    StackPush(&obj->Pushs1,x);
}

dequeue (pop)

From the graphical analysis, you must first perform a data entry, and then pop the stack with data.

First determine whether the second stack is an empty stack, the empty stack can be poured, and then determine whether the first stack has elements.

Pour a top element of the stack into the empty stack, and pop the top element of the original stack, looping until the original stack is empty

Note: When pop is required to return the opposite element, the opposite element is the top element of the stack.

 Then pop the top element of the stack.

int myQueuePop(MyQueue* obj) {
    assert(obj);
    //s2空时需要push进s1元素才能出
    if(StackEmpty(&obj->Pops2))
    {
        while(!StackEmpty(&obj->Pushs1))
        {
            StackPush(&obj->Pops2,StackTop(&obj->Pushs1));
            StackPop(&obj->Pushs1);
        }
    }
    int front=StackTop(&obj->Pops2);
    StackPop(&obj->Pops2);
    return front;
}

Returns the head element of the queue

The head element of the queue is the top element of the non-empty stack after the data is poured once

After making a judgment and pouring, you can return directly.

int myQueuePeek(MyQueue* obj) {
    assert(obj);
    if(StackEmpty(&obj->Pops2))
    {
        while(!StackEmpty(&obj->Pushs1))
        {
            StackPush(&obj->Pops2,StackTop(&obj->Pushs1));
            StackPop(&obj->Pushs1);
        }
    }
    return StackTop(&obj->Pops2);
}

Determine whether the queue is empty and the destruction of the queue

There are also two stacks in the queue. The queue is empty only when the two stacks are empty. You can just return it directly.

When destroying, first destroy the two stacks, and then destroy the queue to prevent memory leaks.

bool myQueueEmpty(MyQueue* obj) {
    return StackEmpty(&obj->Pushs1)&&StackEmpty(&obj->Pops2);
}

void myQueueFree(MyQueue* obj) {
    StackDestory(&obj->Pushs1);
    StackDestory(&obj->Pops2);
    free(obj);
}

Guess you like

Origin blog.csdn.net/weixin_53316121/article/details/123928054
Recommended