栈与队列--用队列实现栈

题目要求: 

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

实现 MyStack 类:

void push(int x) 将元素 x 压入栈顶。
int pop() 移除并返回栈顶元素。
int top() 返回栈顶元素。
boolean empty() 如果栈是空的,返回 true ;否则,返回 false 。

思路: 

由于栈的原则为后进先出,而队列的进出原则为先进先出

当两个队列都为空时,可将元素存入任意一个队列中

当有一个队列存入元素,此后所有的元素都存入这个队列中

为了实现栈顶数据的删除,将队列1中的非末尾数据依次保存在队列2中,使得队列1中只剩最后需要删除的元素,即栈顶元素

同理,如果想删除数字4,则将123保存至队列1,后将队列2中的4删除

插入数据则将数据插入至有数据存放的队列

代码实现:

//请你仅使用两个队列实现一个后入先出(LIFO)的栈
//并支持普通栈的全部四种操作(push、top、pop 和 empty)
#include<stdio.h>
#include<assert.h>
#include<stdbool.h>
#include<stdlib.h>

typedef int QDataType;

typedef struct QueueNode//创建一个链表
{
	struct QueueNode* next;
	QDataType data;
}QNode;


typedef struct Queue//创建一个队列
{
	QNode* head;//指向队头
	QNode* tail;//指向队尾
}Queue;


void QueueInit(Queue* Q1);
void QueueDestory(Queue* Q1);
void QueuePush(Queue* Q1, QDataType x);//队尾入
void QueuePop(Queue* Q1);//队头出
QDataType QueueFront(Queue* Q1);
QDataType QueueBack(Queue* Q1);
int QueueSize(Queue* Q1);
bool QueueEmpty(Queue* Q1);
void QueueInit(Queue* Q1)
{
	assert(Q1);
	Q1->head = Q1->tail = NULL;
}

void QueueDestory(Queue* Q1)
{
	assert(Q1);
	QNode* cur = Q1->head;
	while (cur)
	{
		QNode* next = cur->next;
		free(cur);
		cur = next;
	}
}

void QueuePush(Queue* Q1, QDataType x)
{
	assert(Q1);
	QNode* newnode = (QNode*)malloc(sizeof(QNode));
	if (newnode == NULL)
	{
		printf("malloc fail\n");
		exit(-1);
	}
	newnode->data = x;
	newnode->next = NULL;
	if (Q1->tail == NULL)
	{
		Q1->head = Q1->tail = newnode;
	}
	else
	{
		Q1->tail->next = newnode;//在tail后插入新结点
		Q1->tail = newnode;//将新结点变为为结点
	}
}


void QueuePop(Queue* Q1)
{
	assert(Q1);
	assert(Q1->head);//保证队列存在,并且队列不为空
	if (Q1->head->next == NULL)
	{
		free(Q1->head);
		Q1->head = Q1->tail = NULL;//将队头队尾指针置空,避免野指针问题
	}
	else
	{
		QNode* next = Q1->head->next;
		free(Q1->head);
		Q1->head = next;
	}
}

QDataType QueueFront(Queue* Q1)
{
	assert(Q1);
	assert(Q1->head);

	return Q1->head->data;
}

QDataType QueueBack(Queue* Q1)
{
	assert(Q1);
	assert(Q1->tail);
	return Q1->tail->data;
}

int QueueSize(Queue* Q1)
{
	assert(Q1);
	int size = 0;
	QNode* cur = Q1->head;
	while (cur)
	{
		++size;
		cur = cur->next;
	}
	return size;
}

bool QueueEmpty(Queue* Q1)
{
	assert(Q1);
	return Q1->head == NULL;
}




typedef struct Stack//栈
{
	Queue Q1;
	Queue Q2;

}MyStack;


MyStack* myStackCreate() //初始化
{
	//如下这种方法不可以实现,在函数中创建的变量作为返回值,返回值为局部变量
	//MyStack st;
	//return &st;
	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)
{
	//下面这种方法不可以使用,编译会报错
	//原因是因为QueuePush在定义实现时,插入的数据类型为STDataType
	//if (QueueEmpty(& obj->Q1))//如果Q1为空
	//{
	//	if (QueueSize(&obj->Q2)>1)
	//	{
	//		QueuePush(&obj->Q1, QueueFront(&obj->Q2));//如果Q2存储数据超过1个,则将数据插入Q1中
	//	}
	//	else
	//	{
	//		QueuePop(&obj->Q2);//只剩一个数据时,将Q2中的数据删除
	//	}
	//}
	//else
	//{
	//	if (QueueSize(&obj->Q1) > 1)
	//	{
	//		QueuePush(&obj->Q2, &obj->Q1);//如果Q2存储数据超过1个,则将数据插入Q1中
	//	}
	//	else
	//	{
	//		QueuePop(&obj->Q1);//只剩一个数据时,将Q2中的数据删除
	//	}
	//}

	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) 
{
	if (QueueEmpty(&obj->Q1)&&QueueEmpty(&obj->Q2))
	{
		return true;
	}
	else
	{
		return false;
	}
}

void myStackFree(MyStack* obj) 
{
	QueueDestory(&obj->Q1);
	QueueDestory(&obj->Q2);
	free(obj);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值