通过两个栈实现一个队列(C语言)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_40927789/article/details/79955293

思路:如下图,我们可以定义两个栈,其中一个input用于实现队列的入队列的操作(就是input栈的入栈),另外一个output用于实现出队列和取队首元素的操作(就是output栈的出栈和取栈顶元素)。
这里写图片描述
当我们要出队列或者去队首元素时时,因为出队列和取队首元素要从output栈出,所以要先将input中的元素移到output中(而且谁最后入栈,就先把谁移到output中,这样一来,后入栈(后入队列)的元素,到了output栈中就是在栈底(相当于队尾)了
这里写图片描述
同理,我们需要入队列时,因为入队列操作只能从input栈顶要进行操作,所以需要将output中的元素全部都移动到input栈中。

注意:对于元素的移动,其实由于栈后进先出的特点,我们要将一个栈中的元素移到另外一个栈中,移动完成的结果总是逆序的(入一个栈中的元素为:a b c d 移动到另外一个栈后必然是:d c b a),正式由于这样的特性我们就可以通过两个栈来实现一个队列的情况。
QueueBy2Stack.h文件

#pragma once 

typedef char DataType;

typedef struct Stack
{
    DataType *data;
    //有效元素个数
    int size;
    //表示data段内存中能容纳的元素个数
    int capacity;
}Stack;

typedef struct Queue
{
    Stack input;
    Stack output;
    //队列的有效元素个数
    int size;
}Queue;

//初始化函数
void QueueInit(Queue *queue);
//销毁函数
void QueueDestroy(Queue *queue);
//入栈函数
void QueuePush(Queue *queue,DataType value);
//出栈函数
void QueuePop(Queue *queue);
//取栈顶元素函数
int QueueFront(Queue *queue,DataType *front);

QueueBy2Stack.c文件

#include<stdio.h>
#include<stdlib.h>
#include"QueueBy2Stack.h"

#define Test_Header printf("\n==========%s==========\n",__FUNCTION__);

//栈初始化
void StackInit(Stack *stack)
{
    if(stack == NULL)
    {
        //非法输入
        return;
    }
    stack->size = 0;
    stack->capacity = 1000;
    stack->data = (DataType*)malloc(stack->capacity * sizeof(DataType));
}
//栈销毁函数
void StackDestroy(Stack *stack)
{
    if(stack == NULL)
    {
        //非法输入
        return;
    }
    free(stack->data);
    stack->data = NULL;
    stack->size = 0;
    stack->capacity = 0;
}
//入栈操作
void StackPush(Stack *stack,DataType value)
{
    if(stack == NULL)
    {
        //非法输入
        return;
    }
    if(stack->size >= stack->capacity)
    {
        //栈满了
        return;
    }
    //栈没满
    stack->data[stack->size++] = value;
}
//出栈操作
void StackPop(Stack *stack)
{
    if(stack == NULL)
    {
        //非法输入
        return;
    }
    if(stack->size == 0)
    {
        //空栈
        return;
    }
    stack->size--;
}
//取栈顶元素函数
int StackGetTop(Stack *stack,DataType *value)
{
    if(stack == NULL)
    {
        //非法输入
        return 0;
    }
    if(stack->size == 0)
    {
        //空栈
        return 0;
    }
    *value = stack->data[stack->size-1];
    return 1;
}

//队列初始化函数
void QueueInit(Queue *queue)
{
    if(queue == NULL)
    {
        //非法输入
        return;
    }
    StackInit(&queue->input);
    StackInit(&queue->output);
    queue->size = 0;
}

//队列销毁函数
void QueueDestroy(Queue *queue)
{
    if(queue == NULL)
    {
        //非法输入
        return;
    }
    StackDestroy(&queue->input);
    StackDestroy(&queue->output);
    queue->size = 0;
}

//入队列函数
void QueuePush(Queue *queue,DataType value)
{
    if(queue == NULL)
    {
        //非法输入
        return;
    }
    //将output(用于出队列的栈)中的元素倒腾到input(用于入队列的栈)中
    while(1)
    {
        DataType front;
        int ret = StackGetTop(&queue->output,&front);
        //如果取栈顶元素返回了0,则说明output(用于出队列的栈)中已经没有元素了
        if(ret == 0)
        {
            break;
        }
        //将output中的元素出栈
        StackPop(&queue->output);
        //将output的栈首元素插入到input中
        StackPush(&queue->input,front);
    }
    //倒腾完成以后再将要插入的新元素插入到input栈中
    StackPush(&queue->input,value);
    //将队列元素个数+1
    queue->size++;
}

//出队列函数
void QueuePop(Queue *queue)
{
    if(queue == NULL)
    {
        //非法输入
        return;
    }
    //将input(用于入队列的栈)中的元素倒腾到output(用于出队列的栈)中
    while(1)
    {
        DataType front;
        int ret = StackGetTop(&queue->input,&front);
        //如果取栈顶元素返回了0,则说明该栈中已经没有元素了
        if (ret == 0)
        {
            break;
        }
        //将input中的元素出栈
        StackPop(&queue->input);
        //将input(用于入队列的栈)中的栈顶元素插入到output(用于出队列的栈)中 
        StackPush(&queue->output,front);
    }
    //倒腾完成以后将output(用于出队列的栈)中的栈顶元素出栈(即出队列操作)
    StackPop(&queue->output);
    //队列元素个数-1
    queue->size--;
}

//取队首元素函数
int QueueFront(Queue *queue,DataType *front)
{
    if(queue == NULL)
    {
        //非法输入
        return 0;
    }
    //将input(用于入队列的栈)中的元素倒腾到output(用于出队列的栈)中
    while(1)
    {
        DataType front;
        int ret = StackGetTop(&queue->input,&front);
        //如果取栈顶元素返回了0,则说明该栈中已经没有元素了
        if(ret == 0)
        {
            break;     
        }
        //将input中的元素出栈
        StackPop(&queue->input);
        //将input(用于入队列的栈)中的栈顶元素插入到output(用于出队列的栈)中 
        StackPush(&queue->output,front);
    }
    //取用于出队列的栈的栈首元素(即取出队首元素)
    int ret = StackGetTop(&queue->output,front);
    return ret;
}

//打印队列元素以便观察函数测试结果(其中思路不再详述,与之前函数思路一致)
void PrintQueueElem(Queue *queue,const char *msg)
{
    printf("[%s]\n",msg);
    if(queue == NULL)
    {
        //非法输入
        return;
    }
    if(queue->size == 0)
    {
        //空队列
        return;
    }
    while(1)
    {
        DataType front;
        int ret = StackGetTop(&queue->output,&front);
        if(ret == 0)
        {
            break;
        }
        StackPop(&queue->output);
        StackPush(&queue->input,front);
    }
    int i = 0;
    for(;i < queue->input.size;i++)
    {
        printf("%c ",stack->data[i]);
    }
    printf("\n\n");
}
//以下为测试函数
void TestQueueBy2Stack()
{
    Test_Header;
    Queue queue;
    //队列初始化
    QueueInit(&queue);
    //入队列函数测试
    QueuePush(&queue,'a');
    QueuePush(&queue,'b');
    QueuePush(&queue,'c');
    QueuePush(&queue,'d');
    PrintQueueElem(&queue,"入队列4个元素:a b c d");
    //以下为取队首元素函数测试1
    DataType front;
    int ret = QueueFront(&queue,&front);
    printf("expected ret = 1,actual ret = %d\n",ret);
    printf("expected front = a,actual front = %c\n",front);
    //出队列函数测试
    QueuePop(&queue);
    QueuePop(&queue);
    PrintQueueElem(&queue,"出队列两个元素");
    //取队首元素测试2
    ret = QueueFront(&queue,&front);
    printf("expected ret = 1,actual ret = %d\n",ret);
    printf("expected front = c,actual front = %c\n",front);

    QueuePop(&queue);
    QueuePop(&queue);
    PrintQueueElem(&queue,"将最后两个元素也出队列");
    //取队首元素函数测试3(空队列)
    ret = QueueFront(&queue,&front);
    printf("expected ret = 0,actual ret = %d\n",ret);
    //销毁队列
    QueueDestroy(&queue);
}
//主函数调用测试函数
int main()
{
    TestQueueBy2Stack();
    return 0;
}

测试结果如下图:
这里写图片描述

阅读更多

扫码向博主提问

小心眼儿猫

非学,无以致疑;非问,无以广识
去开通我的Chat快问
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页