232.用栈实现队列(LeetCode)

思路

思路:利用两个栈实现队列先进先出的特性,先将元素导入一个栈内

 

 模拟出队时,则将所有元素导入另一个栈内,此时元素顺序被反转过来,只需要取栈顶数据即可

 

 那我们就可以将两个栈的功能分开,一个专门入push,一个专门出pop。出数据时,如果popst为空,则将pushst的数据导入。

假设pushst入了1234后,反转到popst后,pushst又入了56,这时也是可以的。因为先pop4次,将1 2 3 4依次出栈,popst为空,则再将56导入,再pop2次,以5 6依次出栈。最终依然是1 2 3 4 5 6先入先出的顺序。

 

实现 

实现: 因为C语言没有库可以现成使用,所以我们将写好的栈导入

 先创建MyQueue结构体,包含两个栈结构体。再malloc动态申请MyQueue结构体的空间,最后将两个栈传入初始化函数,进行初始化(记得要加上&取地址符号) 

 

入队过程 ,我们把数据全部导入pushst栈内即可

 

因为peek的功能比较简单,只用返回队列开头元素,所以我们先实现这个功能,等会实现pop再复用peek。 

 返回队列开头元素,我们的核心思路,先判断popst是否为空,如果为空,则循环将pushst中的元素全部导入popst注意:每取出一个栈顶元素,就将该元素pop出栈),最后获取popst的栈顶元素即可

 

 出队过程复用peek的功能,先用front保存队头元素,再将popst的栈顶元素弹出,最后返回front即可

 

 判断栈是否为空,只要当两个栈pushst和popst全为空时,队列才为空,返回true,否则返回false

 

 最后,释放队列空间,可能有人只写了最后一句也给过了,但是其实这是不对的。正确做法是,先将两个栈都销毁(销毁数组),再将MyQueue空间给释放掉,这样才不会造成内存泄漏

 

完整代码附上:

typedef int STDataType;
typedef struct Stack
{
	STDataType* a;
	int top;
	int capacity;
}ST;

//初始化
void STInit(ST* pst);
//销毁
void STDestroy(ST* pst);
//压栈
void STPush(ST* pst, STDataType x);
//出栈
void STPop(ST* pst);
//获取栈顶元素
STDataType STTop(ST* pst);
//检测栈是否为空
bool STEmpty(ST* pst);
//检测栈中有效元素个数
int STSize(ST* pst);

void STInit(ST* pst)
{
	assert(pst);
	
	pst->a = NULL;
	pst->top = 0;//top指向栈顶元素的下一个位置
	pst->capacity = 0;
}

void STDestroy(ST* pst)
{
	assert(pst);
	
	free(pst->a);
	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));

		if (tmp == NULL)
		{
			perror("realloc fail");
			return;
		}

		pst->a = tmp;
		pst->capacity = newCapacity;
	}

	pst->a[pst->top++] = x;
}

void STPop(ST* pst)
{
	assert(pst);
	assert(!STEmpty(pst));
	
	pst->top--;
}

STDataType STTop(ST* pst)
{
	assert(pst);
	assert(!STEmpty(pst));
	
	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 pushst;
    ST popst;
} MyQueue;


MyQueue* myQueueCreate() {
    MyQueue* obj = (MyQueue*)malloc(sizeof(MyQueue));
    if (obj == NULL)
    {
        perror("malloc fail");
        return NULL;
    }

    STInit(&obj->pushst);
    STInit(&obj->popst);

    return obj;
}

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

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

    return front;
}

int myQueuePeek(MyQueue* obj) {
    if (STEmpty(&obj->popst))
    {
        while (!STEmpty(&obj->pushst))
        {
            STPush(&obj->popst, STTop(&obj->pushst));
            STPop(&obj->pushst);
        }
    }

    return STTop(&obj->popst);
}

bool myQueueEmpty(MyQueue* obj) {
    return STEmpty(&obj->pushst)
    && STEmpty(&obj->popst);
}

void myQueueFree(MyQueue* obj) {
    STDestroy(&obj->pushst);
    STDestroy(&obj->popst);
    free(obj);
}

/**
 * Your MyQueue struct will be instantiated and called as such:
 * MyQueue* obj = myQueueCreate();
 * myQueuePush(obj, x);
 
 * int param_2 = myQueuePop(obj);
 
 * int param_3 = myQueuePeek(obj);
 
 * bool param_4 = myQueueEmpty(obj);
 
 * myQueueFree(obj);
*/

猜你喜欢

转载自blog.csdn.net/2301_79188764/article/details/134394866