第九期——用队列实现栈

因为本期使用C语言来实现代码,由于C语言不支持队列,所以我们要先实现队列的模拟。

队列的结构特点和实现

队列的结构特点:只允许在一端进行插入数据操作,在另一端进行删除数据的操作,队列具有先进先出的特点。如图:

队列的实现:可以用数组或者链表来实现队列,如果用数组来实现队列,出队列涉及数组元素的移动,效率比较低下;如果用链表实现队列,将单链表头设为队头,链表的尾就是队尾,入队就是尾插,出队就是头删,另外在单链表的结构基础上增加一个尾指针指向链表的尾节点,方便尾插效率会快很多。

用链表实现队列:

typedef int QDataType;

//链式结构

typedef struct QueueNode

{

    QDataType data;

    struct QueueNode* next;

}QNode;

//队列的结构

typedef struct Queue

{

    QNode* head;

    QNode* tail;

    int size;

 }Queue;

void QueueInit(Queue* pq);//初始化队列

void QueueDestroy(Queue* pq);//销毁队列

void QueuePush(Queue* pq,QDataType x);//队尾入队列

void QueuePop(Queue* pq);//队头出队列

int QueueSize(Queue* pq);//获取队列有效元素的个数

bool QueueEmpty(Queue* pq);//判断队列是否为空

QDataType QueueFront(Queue* pq);//获取队头元素

QDataType QueueBack(Queue* pq);//获取队尾元素

void QueueInit(Queue* pq)
{
	assert(pq);
	pq->tail = pq->head = NULL;
	pq->size = 0;
}

void QueueDestroy(Queue* pq)
{
	assert(pq);
	QNode* cur = pq->head;
	while (cur)
	{
		QNode* next = cur->next;
		free(cur);
		cur = next;
	}
	pq->head = pq->tail = NULL;
	pq->size = 0;
}

void QueuePush(Queue* pq, QDataType x)
{
	assert(pq);
	QNode* newnode = (QNode*)malloc(sizeof(QNode));
	if (newnode == NULL)
	{
		perror("malloc");
		return;
	}
	newnode->data = x;
	newnode->next = NULL;

	if (pq->head == NULL)
	{
		assert(pq->tail == NULL);
		pq->head = pq->tail = newnode;
	}
	else
	{
		pq->tail->next = newnode;
		pq->tail = newnode;
	}
	pq->size++;
}

bool QueueEmpty(Queue* pq)
{
	assert(pq);

	return pq->size == 0;
}

void QueuePop(Queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(pq));
	if (pq->head->next == NULL)
	{
		free(pq->head);
		pq->head = pq->tail = NULL;
	}
	else
	{
		QNode* newhead = pq->head->next;
		free(pq->head);
		pq->head = newhead;
	}
	pq->size--;
}

int QueueSize(Queue* pq)
{
	assert(pq);
	return pq->size;
}

QDataType QueueFront(Queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(pq));
	return pq->head->data;
}

QDataType QueueBack(Queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(pq));
	return pq->tail->data;
}

题目:用队列实现栈

查看原题目请点击这里~

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

注意:

  • 你只能使用队列的标准操作 —— 也就是 push to backpeek/pop from frontsize 和 is empty 这些操作。
  • 你所使用的语言也许不支持队列。 你可以使用 list (列表)或者 deque(双端队列)来模拟一个队列 , 只要是标准的队列操作即可。

typedef struct {

   

} MyStack;

MyStack* myStackCreate() {

   

}

void myStackPush(MyStack* obj, int x) {

   

}

int myStackPop(MyStack* obj) {

   

}

int myStackTop(MyStack* obj) {

  

}

bool myStackEmpty(MyStack* obj) {  

}

void myStackFree(MyStack* 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);

*/

思路

用队列实现入栈操作很容易,由于栈只允许在固定的一端进行插入和删除元素操作,而队列只允许在一端进行插入数据操作,在另一端进行删除数据的操作,所以我们要出栈的时候要拿到队列队尾的元素4,而把队尾前面的元素1、2、3移动到另一个空队列中。

于是,整体思路大体为:

两个队列初始状态都为空,入栈的时候将n个数据从队尾入队到第一个队列中,如果需要出栈,也就是删除队尾元素,就将第一个队列中前n-1个数据都移动到第二个队列中,此时第一个队列中剩下的元素就是我们要删除的栈顶元素,删除元素之后,第一个队列就为空,此时如果想要入栈插入元素,就把元素入队到第二个队列,如果想要出栈,再利用第一个队列移动元素。

也就是说,两个队列保持一个为空,向不为空的队列插入元素,如果想要删除元素,就用空的队列来倒元素。

如果想要获取栈顶元素,我们只要获取队尾元素即可;如果想要判断栈是否为空,就判断两个栈是否都为空。

代码(C语言版)

typedef int QDataType;
typedef struct QueueNode
{
	QDataType data;
	struct QueueNode* next;
}QNode;
typedef struct Queue
{
	QNode* head;
	QNode* tail;
	int size;
 }Queue;

void QueueInit(Queue* pq)
{
	assert(pq);
	pq->tail = pq->head = NULL;
	pq->size = 0;
}
void QueueDestroy(Queue* pq)
{
	assert(pq);
	QNode* cur = pq->head;
	while (cur)
	{
		QNode* next = cur->next;
		free(cur);
		cur = next;
	}
	pq->head = pq->tail = NULL;
	pq->size = 0;
}
void QueuePush(Queue* pq, QDataType x)
{
	assert(pq);
	QNode* newnode = (QNode*)malloc(sizeof(QNode));
	if (newnode == NULL)
	{
		perror("malloc");
		return;
	}
	newnode->data = x;
	newnode->next = NULL;

	if (pq->head == NULL)
	{
		assert(pq->tail == NULL);
		pq->head = pq->tail = newnode;
	}
	else
	{
		pq->tail->next = newnode;
		pq->tail = newnode;
	}
	pq->size++;
}
bool QueueEmpty(Queue* pq)
{
	assert(pq);

	return pq->size == 0;
}

void QueuePop(Queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(pq));
	if (pq->head->next == NULL)
	{
		free(pq->head);
		pq->head = pq->tail = NULL;
	}
	else
	{
		QNode* newhead = pq->head->next;
		free(pq->head);
		pq->head = newhead;
	}
	pq->size--;
}
int QueueSize(Queue* pq)
{
	assert(pq);
	return pq->size;
}
QDataType QueueFront(Queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(pq));
	return pq->head->data;
}
QDataType QueueBack(Queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(pq));
	return pq->tail->data;
}



typedef struct {
    Queue queue1;
    Queue queue2;
} MyStack;


MyStack* myStackCreate() {
    MyStack* pst=(MyStack*)malloc(sizeof(MyStack));
    if(pst==NULL)
    {
        perror("malloc");
        return NULL;
    }
    QueueInit(&pst->queue1);
    QueueInit(&pst->queue2);
    return pst;
}

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

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

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

    }
}

bool myStackEmpty(MyStack* obj) {
    bool ret=QueueEmpty(&obj->queue1)&&QueueEmpty(&obj->queue2);
    return ret;
}

void myStackFree(MyStack* obj) {
    QueueDestroy(&obj->queue1);
    QueueDestroy(&obj->queue2);
    free(obj);
}

持续更新,下期见

(下期内容:用栈实现队列)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值