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

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

https://leetcode-cn.com/problems/yong-liang-ge-zhan-shi-xian-dui-lie-lcof/
用两个栈实现队列(C语言版)_第1张图片

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

思路:双栈。

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

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

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

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

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

用两个栈实现队列(C语言版)_第4张图片

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

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

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

初始状态:
用两个栈实现队列(C语言版)_第5张图片
push元素到s1后:
用两个栈实现队列(C语言版)_第6张图片
这是以队列的视角来看就是

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

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

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

#include 
#include 
#include 
#include 
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;
}

你可能感兴趣的:(剑指offer,c语言,数据结构)