栈和队列——用队列实现栈

题目中给出,让我们应用两个队列实现栈,首先我们先来想一下,栈是先进后出,队列是先进先出。所以我们就需要应用两个队列来回导才能实现栈的特点。因为这道题是基于队列来实现的,所以在下方若有看不懂的函数名称可以去栈和队列(二)中找到。

1.MyStrack

首先我们需要在结构体中存储我们的两个队列,后续方便通过结构体来调用两个队列。

typedef struct 
{
    Queue q1;
    Queue q2;
} MyStack;

2.myStackCreate()

对其进行初始化,首先我们需要先开辟一块空间用来存储两个队列。然后我们调用QueueInit()函数来对两个队列进行初始化。

MyStack* myStackCreate() 
{
    MyStack*obj=(MyStack*)malloc(sizeof(MyStack));
    QueueInit(&(obj->q1));
    QueueInit(&(obj->q2));
    return obj;
}

3.myStackPush()

对栈进行插入,首先我们需要调用QueueEmpty()函数判断两个队列哪个不为空,再调用QueuePush()函数将数据直接插入到不为空的那个队列里就可以了。

void myStackPush(MyStack* obj, int x) 
{
    if(!QueueEmpty(&(obj->q1)))
    {
        QueuePush(&(obj->q1),x);
    }
    else
    {
        QueuePush(&(obj->q2),x);
    }
}

4.myStackPop()

因为我们已经知道栈的删除是删除后进的数据,队列的删除是删除先进的数据。其删除的位置不同,所以不能混为一谈。所以我们需要把非空的队列中的前size-1个数据都挪到空的队列中。首先我们就需要先判断那个队列是空的。所以,依据我们之前做过的题,我们可以使用假设法,先假设q1为空,若q1不为空,再将空的改为q2。现在我们就用empty和nonempty来代表空队列和非空队列了。然后我们应用QueuePush()函数和QueueFront()函数来将非空队列中的头数据插入到空队列中,直到非空链表中的数据个数为1时停止,取出非空队列中的数据,就是我们需要的数据。

int myStackPop(MyStack* obj) 
{
    Queue*empty=&(obj->q1);
    Queue*nonempty=&(obj->q2);
    if(!QueueEmpty(&(obj->q1)))
    {
        empty=&(obj->q2);
        nonempty=&(obj->q1);
    }
    while(QueueSize(nonempty)>1)
    {
        QueuePush(empty,QueueFront(nonempty));
        QueuePop(nonempty);
    }
    int top=QueueFront(nonempty);
    QueuePop(nonempty);
    return top;
}

5.myStackTop()

由于栈是先进后出,队列是先进先出,所以栈的Top就是队列中后进的那个数据。所以我们首先需要判断哪个队列为非空队列,再调用QueueBack()函数返回非空队列中的尾数据就可以了。

int myStackTop(MyStack* obj) 
{
   if(!QueueEmpty(&(obj->q1)))
   {
    return QueueBack(&(obj->q1));
   }
   else
   {
    return QueueBack(&(obj->q2));
   }
}

6.myStackEmpty()

判断队列是否为空,需要两个队列同时为空,所以只需要调用QueueEmpty()函数,并返回两个队列进行与运算的值就可以了。

bool myStackEmpty(MyStack* obj) 
{
    return QueueEmpty(&(obj->q1))&&QueueEmpty(&(obj->q2));   
}

7.myStackFree()

由于我们刚刚将两个队列存储在了一个结构体中,所以在销毁时不能直接将结构体销毁,而是应该先销毁两个队列,再销毁结构体。

void myStackFree(MyStack* obj) 
{
    QueueDestory(&(obj->q1));
    QueueDestory(&(obj->q2));
    free(obj);
}

总结

整道题的基本思路与代码就讲解完毕了,下面附上本题的完整代码,如果大家感兴趣的话可以自行尝试哦~

typedef int QDataType;
typedef struct QueueNode
{
	QDataType val;
	struct QueueNode* next;
}QNode;


typedef struct Queue
{
	QNode* phead;
	QNode* ptail;
	int size;
}Queue;

//队列的初始化
void QueueInit(Queue* pq);
//队列的插入
void QueuePush(Queue* pq, QDataType x);
//队列的删除
void QueuePop(Queue* pq);
//统计队列内的数据个数
int QueueSize(Queue* pq);
//获取队列的头数据
QDataType QueueFront(Queue* pq);
//获取队列的尾数据
QDataType QueueBack(Queue* pq);
//队列的判空
bool QueueEmpty(Queue* pq);
//队列的销毁
void QueueDestory(Queue* pq);

//队列的初始化
void QueueInit(Queue* pq)
{
	assert(pq);
	pq->phead = NULL;
	pq->ptail = NULL;
	pq->size = 0;
}
//队列的插入
void QueuePush(Queue* pq, QDataType x)
{
	assert(pq);
	QNode* newnode = (QNode*)malloc(sizeof(QNode));
	if (newnode == NULL)
	{
		perror("malloc fail");
		exit(1);
	}
	newnode->next = NULL;
	newnode->val = x;
	if (pq->ptail == NULL)
	{
		pq->phead = pq->ptail = newnode;
	}
	else
	{
		pq->ptail->next = newnode;
		pq->ptail = newnode;
	}
	pq->size++;
}
//队列的删除
void QueuePop(Queue* pq)
{
	assert(pq);
	assert(pq->size != 0);

	//方法一:后判是否为只剩一个节点
	//QNode* next = pq->phead->next;
	//free(pq->phead);
	//pq->phead = next;
	//if (pq->phead == NULL)
	//{
	//	pq->ptail = NULL;
	//}
	//pq->size--;


	//方法二:先判是否为只剩一个节点
	if (pq->phead->next == NULL)
	{
		pq->phead = pq->ptail = NULL;
		pq->size = 0;
	}
	else
	{
		QNode* next = pq->phead->next;
		free(pq->phead);
		pq->phead = next;
		pq->size--;
	}
}


//统计队列内的数据个数
int QueueSize(Queue* pq)
{
	assert(pq);
	return pq->size;
}

//获取队列的头数据
QDataType QueueFront(Queue* pq)
{
	assert(pq);
	assert(pq->phead);
	return pq->phead->val;
}
//获取队列的尾数据
QDataType QueueBack(Queue* pq)
{
	assert(pq);
	assert(pq->ptail);
	return pq->ptail->val;
}


//队列的判空
bool QueueEmpty(Queue* pq)
{
	assert(pq);
	return pq->size == 0;

}


//队列的销毁
void QueueDestory(Queue* pq)
{
	assert(pq);
	QNode* pcur = pq->phead;
	while (pcur)
	{
		QNode* next = pcur->next;
		free(pcur);
		pcur = next;
	}
	pq->phead = pq->ptail = NULL;
	pq->size = 0;
}

typedef struct 
{
    Queue q1;
    Queue q2;
} MyStack;


MyStack* myStackCreate() 
{
    MyStack*obj=(MyStack*)malloc(sizeof(MyStack));
    QueueInit(&(obj->q1));
    QueueInit(&(obj->q2));
    return obj;
}

void myStackPush(MyStack* obj, int x) 
{
    if(!QueueEmpty(&(obj->q1)))
    {
        QueuePush(&(obj->q1),x);
    }
    else
    {
        QueuePush(&(obj->q2),x);
    }
}

int myStackPop(MyStack* obj) 
{
    Queue*empty=&(obj->q1);
    Queue*nonempty=&(obj->q2);
    if(!QueueEmpty(&(obj->q1)))
    {
        empty=&(obj->q2);
        nonempty=&(obj->q1);
    }
    while(QueueSize(nonempty)>1)
    {
        QueuePush(empty,QueueFront(nonempty));
        QueuePop(nonempty);
    }
    int top=QueueFront(nonempty);
    QueuePop(nonempty);
    return top;
}

int myStackTop(MyStack* obj) 
{
   if(!QueueEmpty(&(obj->q1)))
   {
    return QueueBack(&(obj->q1));
   }
   else
   {
    return QueueBack(&(obj->q2));
   }
}

bool myStackEmpty(MyStack* obj) 
{
    return QueueEmpty(&(obj->q1))&&QueueEmpty(&(obj->q2));   
}

void myStackFree(MyStack* obj) 
{
    QueueDestory(&(obj->q1));
    QueueDestory(&(obj->q2));
    free(obj);
}

/**
 * Your MyStack struct will be instantiated and called as such:
 * MyStack* obj = myStackCreate();
 * myStackPush(obj, x);
 
 * int param_2 = myStackPop(obj);
 
 * int param_3 = myStackTop(obj);
 
 * bool param_4 = myStackEmpty(obj);
 
 * myStackFree(obj);
*/

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值