用两个栈实现队列(C语言版)

用两个栈实现一个队列。队列的声明如下,请实现它的两个函数 appendTail 和 deleteHead ,分别完成在队列尾部插入整数和在队列头部删除整数的功能。(若队列中没有元素,deleteHead 操作返回 -1 )

https://leetcode-cn.com/problems/yong-liang-ge-zhan-shi-xian-dui-lie-lcof/
在这里插入图片描述

由于C语言的栈要自己实现。前面写好栈的一些接口,代码在最后。

思路:双栈。

先说两个栈的作用:一个栈用于插入,一个栈用于删除。

1.创建队列,两个栈即可。假定s1用于插入,s2用于删除
在这里插入图片描述
将两个栈初始化好。
在这里插入图片描述
2.尾插,直接在s1里面插入就可以。
在这里插入图片描述
3.尾删。由于队列的先进先出的,因此要借助s2来删除。

基本逻辑是:当要删除时,把s1里的元素pop出来,然后push到s2里面。直到s1为空,此时s2的top就是队列的头部,也就是要删除的元素。

在移动数据时,这里有四种情况,每一种都考虑好就行了。

  1. s1和s2都是空
  2. s1为空,s2不为空
  3. s1不为空,s2为空
  4. s1和s2都不为空

在这里插入图片描述

s1和s2都是空
直接返回-1即可,因为整个队列都是空了。

s1为空,s2不为空
这种情况就是没有把原先的元素全部pop完的情况,直接pop s2的top就可以了。
s1不为空,s2为空
这就是还没开始删的时候,直接把s1的元素全部倒到s2,然后pop s2的top就可以了。

两个都不是空
这种形况发生在:刚把s1里面的元素push到s2进行删除后,立刻push了元素。

初始状态:

push元素到s1后:
在这里插入图片描述
这是以队列的视角来看就是

6 5 4 3 2 1--------->5 4 3 2 1-------->5 4 3 2 1 1
因此直接pop s2的top就可以了。

可以总结一下:
四种情况中 s1为空,s2不为空和两个都不是空的代码是一样的,其他两种情况单独写就好了。

代码(大部分都是实现栈的接口):

#include <stdio.h>
#include <stdbool.h>
#include <malloc.h>
#include <assert.h>
typedef int StackDataType;

typedef struct stack
{
	StackDataType* a;//dynamic
	int top;
	int capacity;
}stack;



void StackInit(stack* p);
void stackDestroy(stack* p);
void stackPush(stack* p, StackDataType x);
void stackPop(stack* p);
StackDataType stackTop(stack* p);
int stackSize(stack* p);
bool stackEmpty(stack* p);

void StackInit(stack* p)
{
	p->a = (StackDataType*)malloc(sizeof(StackDataType) * 4);
	p->top = 0;
	p->capacity = 4;
}

void stackDestroy(stack* p)
{
	free(p->a);
	p->capacity = p->top = 0;
	p->a = NULL;
	p = NULL;
}

void stackPush(stack* p, StackDataType x)
{
	assert(p);
	if (p->capacity == p->top)
	{
		p->capacity *= 2;
		p->a = (StackDataType*)realloc(p->a, sizeof(StackDataType) * p->capacity);
		if (p == NULL)
		{
			printf("realloc fail");
			exit(-1);
		}
	}
	p->a[p->top++] = x;
}

void stackPop(stack* p)
{
	assert(p);
	p->top--;
}

StackDataType stackTop(stack* p)
{
	assert(p);
	return p->a[p->top - 1];
}

int stackSize(stack* p)
{
	return p->top;
}

bool stackEmpty(stack* p)
{
	return p->top == 0;
}

typedef struct {
    stack s1;
    stack s2;
} CQueue;


CQueue* cQueueCreate() {
    CQueue* obj = (CQueue*)malloc(sizeof(stack)*2);
    StackInit(&(obj->s1));
    StackInit(&(obj->s2));
    return obj;
}

void cQueueAppendTail(CQueue* obj, int value) {
    stackPush(&obj->s1,value);
}

int cQueueDeleteHead(CQueue* obj) {
    //把四种情况都罗列出来就可以了。
    if(stackEmpty(&obj->s1)&&stackEmpty(&obj->s2))//两个都是空
        return -1;
    
    if(stackEmpty(&obj->s2))//如果s2是空
    {
        while(!stackEmpty(&obj->s1))
        {
            stackPush(&obj->s2,stackTop(&obj->s1));
            stackPop(&obj->s1);
        }
        printf("1\n");
        int top = stackTop(&obj->s2);
        stackPop(&obj->s2);
        return top;
    }
    if(!stackEmpty(&obj->s2) && stackEmpty(&obj->s1))//如果s2不是空且s1是空
    {
        printf("2\n");
        int top = stackTop(&obj->s2);
        stackPop(&obj->s2);
        return top;
    }
    if(!stackEmpty(&obj->s1)&&!stackEmpty(&obj->s2))//两个都不是空
    {
        int top = stackTop(&obj->s2);
        stackPop(&obj->s2);
        return top;
    }
    return -1;
}

void cQueueFree(CQueue* obj) {
    stackDestroy(&obj->s1);
    stackDestroy(&obj->s2);
    free(obj);
    obj = NULL;
}
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值