队列经典问题——用队列实现栈

注:前两篇博客已经具体实现了栈和队列,本篇博客在需要用到队列的地方会直接使用它的操作函数。

目录

用队列实现栈

思路

示例

代码实现

入栈

出栈

获取栈顶元素

检测栈是否为空

销毁栈

全部代码

测试用例


用队列实现栈

要求:仅使用两个队列实现一个后入先出(LIFO)的栈,并支持普通栈的全部四种操作(pushtoppop 和 empty)。

队列是一种先入先出的数据结构,而栈是一种后入先出的数据结构,那么如何用两个队列实现栈呢?我们知道,这两种数据结构入数据的方式是相同的,那么只需用队列先入先出的逻辑来实现栈后入先出的逻辑即可。

思路

由于入数据的方式相同,最开始我们可以将数据先入到其中一个队列。出数据时,由于需要出队尾的第一个元素,我们可以将这个非空队列(现存有数据的队列)中除队尾元素外的所有元素都倒入到另一个空队列(现未存数据的队列)中,这样,需要出的元素就到了队列的首位,然后直接出这个元素即可,之后入数据入到有元素的队列。

示例

下面是出数据 5 的示例,先将数据1,2,3,4倒入到最初为空队列的 emptyQ 中,然后出最初为nonemptyQ队列中的剩下一个元素。这样便利用两个队列的性质实现了栈的性质。

注:这里的 nonemptyQ 和 emptyQ 只是一开始对这两个队列做的标识,方便我们在实际操作中使用这两个队列。

队列经典问题——用队列实现栈_第1张图片

代码实现

我们可以使用的队列操作有:QueueInit、QueueDestroy、QueuePush、QueuePop、QueueFront、QueueBack、QueueSize、QueueEmpty。

我们先创建好需要用两个队列实现的栈:

(假设这里的Queue是我们已经定义好的队列)

typedef struct 
{
    Queue q1;
    Queue q2;
} MyStack; 


MyStack* myStackCreate() 
{
    MyStack* ps = (MyStack*)malloc(sizeof(MyStack));
    if(ps == NULL)
    {
        printf("malloc fail\n");
        exit(-1);
    }
    QueueInit(&ps->q1);
    QueueInit(&ps->q2);

    return ps;
}

下面给出需要我们实现的接口:

//将元素 x 压入栈顶
void myStackPush(MyStack* obj, int x);

//移除并返回栈顶元素
int myStackPop(MyStack* obj);

//返回栈顶元素
int myStackTop(MyStack* obj);

//如果栈是空的,返回 true ;否则,返回 false
bool myStackEmpty(MyStack* obj);

//销毁栈
void myStackFree(MyStack* obj);

入栈

将需要入栈的元素入到其中不为空的队列中,当两个队列都为空时,元素入到其中一个队列即可。

void myStackPush(MyStack* obj, int x) 
{
    if(!QueueEmpty(&obj->q1))
    {
        QueuePush(&obj->q1, x);
    }
    else
    {
        QueuePush(&obj->q2, x);
    }
}

出栈

将非空队列中除最后一个外的其它元素倒入到另一个队列中,保存剩下元素作为返回值后出队列。

int myStackPop(MyStack* obj) 
{
    //先假设出空与非空队列,在根据实际判断出空与非空队列
    Queue* emptyQ = &obj->q1;
    Queue* nonemptyQ = &obj->q2;
    if(!QueueEmpty(&obj->q1))
    {
        emptyQ = &obj->q2;
        nonemptyQ = &obj->q1;
    }
    //倒数据
    while(QueueSize(nonemptyQ) > 1)
    {
        QueuePush(emptyQ,QueueFront(nonemptyQ));
        QueuePop(nonemptyQ);
    }
    //先保存,后出
    int top = QueueFront(nonemptyQ);
    QueuePop(nonemptyQ);

    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);
}

全部代码

typedef struct 
{
    Queue q1;
    Queue q2;
} MyStack; 


MyStack* myStackCreate() 
{
    MyStack* ps = (MyStack*)malloc(sizeof(MyStack));
    if(ps == NULL)
    {
        printf("malloc fail\n");
        exit(-1);
    }
    QueueInit(&ps->q1);
    QueueInit(&ps->q2);

    return ps;
}

void myStackPush(MyStack* obj, int x) 
{
    if(!QueueEmpty(&obj->q1))
    {
        QueuePush(&obj->q1, x);
    }
    else
    {
        QueuePush(&obj->q2, x);
    }
}

int myStackPop(MyStack* obj) 
{
    Queue* emptyQ = &obj->q1;
    Queue* nonemptyQ = &obj->q2;
    if(!QueueEmpty(&obj->q1))
    {
        emptyQ = &obj->q2;
        nonemptyQ = &obj->q1;
    }
    //倒数据
    while(QueueSize(nonemptyQ) > 1)
    {
        QueuePush(emptyQ,QueueFront(nonemptyQ));
        QueuePop(nonemptyQ);
    }
    
    int top = QueueFront(nonemptyQ);
    QueuePop(nonemptyQ);

    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);
}

测试用例

void TestMyStack()
{
	MyStack* ST = myStackCreate();
	myStackPush(ST, 1);
	myStackPush(ST, 2);
	myStackPush(ST, 3);
	myStackPush(ST, 4);
	myStackPush(ST, 5);
	printf("%d\n", myStackTop(ST));

	printf("%d\n", myStackPop(ST));
	printf("%d\n", myStackPop(ST));

	printf("%d\n", myStackTop(ST));

	while (!myStackEmpty(ST))
	{
		printf("%d ", myStackPop(ST));
	}
	printf("\n");

	myStackFree(ST);

}

int main()
{
	TestMyStack();
	return 0;
}

队列经典问题——用队列实现栈_第2张图片

你可能感兴趣的:(数据结构,栈,队列)