用两个栈实现队列

首先我们想一下,栈是先进后出,而队列是先进先出的

所以我们想实现队列的插入和删除,就必要的使用两个栈

用两个栈实现队列_第1张图片

插入的方法就是栈的插入,但删除的方法则是先取栈顶的元素并插入到另一个栈,全部取过去后,将该栈删空,再另一个栈中删除所需删的值

用用两个栈可以将栈中的值倒置,正好可以满足队列的先进先出

专门用来插入的栈我们称之为 push_stack 专门用来删除的栈我们称之为 pop_stack

现在我们开始对这题的几个接口进行代码书写

创建结构体包含两个栈

typedef struct {
    ST push_stack;
    ST pop_stack;
} MyQueue;

 队列的创建

MyQueue* myQueueCreate()
{
    MyQueue* obj = (MyQueue*)malloc(sizeof(MyQueue));
    STInit(&(obj->push_stack));
    STInit(&(obj->pop_stack));
    return obj;
}

队列的插入

void myQueuePush(MyQueue* obj, int x)
{
    STPush(&(obj->push_stack), x);
}

返回队列开头的元素

队列开头的值需要我们先将 push_stack 的数据导到 pop_stack 中,导一个删一个,再取 pop_stack 的栈顶数据就是队列开头

如果 pop_stack 中已有数据了,则直接取栈顶数据就好了

int myQueuePeek(MyQueue* obj)
{
    if (STEmpty(&(obj->pop_stack)))
    {
        while (!STEmpty(&(obj->push_stack)))
        {
            int top = STTop(&(obj->push_stack));
            STPush(&(obj->pop_stack), top);
            STPop(&(obj->push_stack));
        }
    }
    return STTop(&(obj->pop_stack));
}

删除元素并返回该元素

删除元素的方法我们之前讲过了,也就是将 push_stack 的元素依次插入到 pop_stack 中并删除在 push_stack 中的元素,再从 pop_stack 中删除所需删的元素

有没有感觉很熟悉? 我们前面的返回队列开头元素不是也有同样的操作嘛?

所以我们先取队列开头元素,此时 push_stack 中的元素已经全插到 pop_stack 中了,不用再做判断再进行重复操作了

int myQueuePop(MyQueue* obj)
{
    int front = myQueuePeek(obj);
    STPop(&(obj->pop_stack));
    return front;
}

判空

两个栈都为空的时候才为空

bool myQueueEmpty(MyQueue* obj)
{
    return STEmpty(&(obj->pop_stack)) && STEmpty(&(obj->push_stack));
}

队列的销毁

void myQueueFree(MyQueue* obj)
{
    STDestory(&(obj->push_stack));
    STDestory(&(obj->pop_stack));
    free(obj);
}

完整代码呈现

#pragma once
#include 
#include 
#include 
#include 
typedef char STDataType;
typedef struct Stack
{
	STDataType* a;  //开辟数组
	int top;    //指向栈顶或栈顶的后一个位置(据情况而定注意前后对应),指的是数组的下标
	int capacity;   //空间中元素的个数
}ST;

//初始化栈
void STInit(ST* pst)
{
	assert(pst);
	pst->a = NULL;
	//top 指向栈顶的下一个位置
	pst->top = 0;
	//top 指向栈顶数据的位置
	//pst->top = -1;
	pst->capacity = 0;
}
//销毁栈
void STDestory(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, newcapacity * sizeof(STDataType));
		//判断 tmp 是否开辟成功
		if (tmp == NULL)
		{
			perror("realloc fail");
			return -1;
		}
		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);

	return pst->top == 0;
}
//获取数据的个数
int STSize(ST* pst)
{
	assert(pst);
	return pst->top;
}

//用栈实现队列的功能
typedef struct {
	ST push_stack;
	ST pop_stack;
} MyQueue;
//创建队列
MyQueue* myQueueCreate()
{
	MyQueue* obj = (MyQueue*)malloc(sizeof(MyQueue));
	STInit(&(obj->push_stack));
	STInit(&(obj->pop_stack));
	return obj;
}
//插入元素
void myQueuePush(MyQueue* obj, int x)
{
	STPush(&(obj->push_stack), x);
}
//删除元素并返回该元素
int myQueuePop(MyQueue* obj)
{
	int front = myQueuePeek(obj);
	STPop(&(obj->pop_stack));
	return front;
}
//返回队列开头的元素
int myQueuePeek(MyQueue* obj)
{
	if (STEmpty(&(obj->pop_stack)))
	{
		while (!STEmpty(&(obj->push_stack)))
		{
			int top = STTop(&(obj->push_stack));
			STPush(&(obj->pop_stack), top);
			STPop(&(obj->push_stack));
		}
	}
	return STTop(&(obj->pop_stack));
}
//判空
bool myQueueEmpty(MyQueue* obj)
{
	return STEmpty(&(obj->pop_stack)) && STEmpty(&(obj->push_stack));
}
//队列的销毁
void myQueueFree(MyQueue* obj)
{
	STDestory(&(obj->push_stack));
	STDestory(&(obj->pop_stack));
	free(obj);
}

你可能感兴趣的:(数据结构,算法)