【剑指offer】两个队列实现堆栈

转载请注明出处:http://blog.csdn.net/ns_code/article/details/25076689


    题目:用两个队列模拟一个栈,即用两个队列的出队和入队操作。来实现栈的出栈和入栈操作。

    思路:略微画下草图。便不难想出该题的解决方法。思路例如以下:

如果有两个队列Q1和Q2,当二者都为空时,入栈操作能够用入队操作来模拟。能够随便选一个空队列,如果选Q1进行入栈操作。如今如果a,b,c依次入栈了(即依次进入队列Q1)。这时如果想模拟出栈操作,则须要将c出栈,由于在栈顶。这时候能够考虑用空队列Q2。将a,b依次从Q1中出队,而后进入队列Q2,将Q1的最后一个元素c出队就可以,此时Q1变为了空队列,Q2中有两个元素。队头元素为a,队尾元素为b,接下来如果再运行入栈操作,则须要将元素进入到Q1和Q2中的非空队列,即进入Q2队列,出栈的话,就跟前面的一样,将Q2除最后一个元素外所有出队,并依次进入队列Q1,再将Q2的最后一个元素出队就可以。

    实现代码例如以下:

/*
用两个队列模拟入栈操作
*/
void push(PQUEUE pS1,PQUEUE pS2,int val)
{
	if(is_empty(pS2))
		en_queue(pS1, val);
	else
		en_queue(pS2, val);
}

/*
用两个队列模拟出栈操作
*/
bool pop(PQUEUE pS1,PQUEUE pS2,int *pData)
{
	if(is_empty(pS1) && is_empty(pS2))
		return false;

	int DelData;
	if(!is_empty(pS2))
	{
		int len = length(pS2);
		while(len-- > 1)
		{
			de_queue(pS2,&DelData);
			en_queue(pS1,DelData);
		}
		//将队列的最后一个元素出队。作为出栈元素
		de_queue(pS2,pData);
		return true;
	}
	if(!is_empty(pS1))
	{
		int len = length(pS1);
		while(len-- > 1)
		{
			de_queue(pS1,&DelData);
			en_queue(pS2,DelData);
		}
		//将队列的最后一个元素出队,作为出栈元素
		de_queue(pS1,pData);
		return true;
	}
}

    完整的代码(用的曾经写的链式队列)例如以下:

/*******************************************************************
题目:用两个队列模拟一个栈
*******************************************************************/

#include<stdio.h>
#include<stdlib.h>

typedef struct Node
{
	int data;
	struct Node *pNext;
}NODE,*PNODE;

typedef struct Queue
{
	PNODE front;  //队头指针
	PNODE rear;   //队尾指针
}QUEUE,*PQUEUE;

PQUEUE create_queue();
bool is_empty(PQUEUE);
void en_queue(PQUEUE, int);
bool de_queue(PQUEUE,int *);
void destroy_queue(PQUEUE);
void traverse_queue(PQUEUE);
int length(PQUEUE);
void push(PQUEUE,PQUEUE,int);
bool pop(PQUEUE,PQUEUE,int *);

int main()
{
	int pData;         //用来保存出队的元素值

	//创建队列并进行入队測试
	PQUEUE pS1 = create_queue();
	PQUEUE pS2 = create_queue();
	push(pS1,pS2,4);
	push(pS1,pS2,5);
	printf("the length of pS1: %d\n",length(pS1));
	printf("the length of pS2: %d\n",length(pS2));
	if(pop(pS1,pS2,&pData))
		printf("%d is pop out\n",pData);
	else
		printf("Stack is empty,can not pop\n");
	printf("the length of pS1: %d\n",length(pS1));
	printf("the length of pS2: %d\n",length(pS2));
	push(pS1,pS2,6);
	printf("the length of pS1: %d\n",length(pS1));
	printf("the length of pS2: %d\n",length(pS2));
	push(pS1,pS2,7);
	printf("the length of pS1: %d\n",length(pS1));
	printf("the length of pS2: %d\n",length(pS2));
	if(pop(pS1,pS2,&pData))
		printf("%d is pop out\n",pData);
	else
		printf("Stack is empty,can not pop\n");
	printf("the length of pS1: %d\n",length(pS1));
	printf("the length of pS2: %d\n",length(pS2));
	if(pop(pS1,pS2,&pData))
		printf("%d is pop out\n",pData);
	else
		printf("Stack is empty,can not pop\n");
	printf("the length of pS1: %d\n",length(pS1));
	printf("the length of pS2: %d\n",length(pS2));
	if(pop(pS1,pS2,&pData))
		printf("%d is pop out\n",pData);
	else
		printf("Stack is empty,can not pop\n");
	printf("the length of pS1: %d\n",length(pS1));
	printf("the length of pS2: %d\n",length(pS2));
	if(pop(pS1,pS2,&pData))
		printf("%d is pop out\n",pData);
	else
		printf("Stack is empty,can not pop\n");

	return 0;
}

/*
创建一个空队列,队头指针和队尾指针都指向头结点,
头结点中不存放数据,仅仅存放指针
*/
PQUEUE create_queue()
{
	PQUEUE pS = (PQUEUE)malloc(sizeof(Queue));
	pS->front = (PNODE)malloc(sizeof(NODE));
	if(!pS || !pS->front)
	{
		printf("pS or front malloc failed!!");
		exit(-1);
	}
	else
	{
		pS->rear = pS->front;
		pS->front->pNext = NULL;
	}
	return pS;
}

/*
推断队列是否为空
*/
bool is_empty(PQUEUE pS)
{
	if(pS->front == pS->rear)
		return true;
	else
		return false;
}

/*
进队函数,从队尾进队,队头指针保持不变
*/
void en_queue(PQUEUE pS, int e)
{
	PNODE pNew = (PNODE)malloc(sizeof(NODE));
	if(!pNew)
	{
		printf("pNew malloc failed");
		exit(-1);
	}
	else
	{
		pNew->data = e;
		pNew->pNext = NULL;
		pS->rear->pNext = pNew;
		pS->rear = pNew;
	}
	return;
}

/*
出队函数,从队头出队,队尾指针保持不变,但当最后一个元素出队时,
须要对队尾指针又一次赋值,使其指向头结点
*/
bool de_queue(PQUEUE pS,int *pData)
{
	if(is_empty(pS))
		return false;
	else
	{
		PNODE p = pS->front->pNext;
		*pData = p->data;
		pS->front->pNext = p->pNext;

		//这里是队列头元素出队的特殊情况,普通情况下,删除队头元素时
		//仅需改动头结点中的指针。但当队列中最后一个元素被删除时。
		//队列尾指针也丢失了,因此需对队尾指针又一次赋值(指向头结点)。
		if(pS->rear == p)
			pS->rear = pS->front;
		free(p);
	}
	return true;
}

/*
遍历队列。从对头向队尾依次输出队中的元素
*/
void traverse_queue(PQUEUE pS)
{
	if(is_empty(pS))
		printf("there is no data in the queue!\n");
	else
	{
		PNODE pCurrent = pS->front->pNext;
		printf("Now datas int the queue are:\n");
		while(pCurrent)
		{
			printf("%d ",pCurrent->data);
			pCurrent = pCurrent->pNext;
		}
		printf("\n");
	}
	return;
}

/*
求队列的长度
*/
int length(PQUEUE pS)
{
	int count = 0;
	PNODE pCurrent = pS->front->pNext;
	while(pCurrent)
	{
		count++;
		pCurrent = pCurrent->pNext;
	}
	return count;
}

/*
销毁队列,头结点也被销毁,最后也将pS节点销毁,并将其指向为空。避免垂直指针的产生
*/
void destroy_queue(PQUEUE pS)
{
	if(is_empty(pS))
		return;
	else
	{
		while(pS->front)
		{
			pS->rear = pS->front->pNext;
			free(pS->front);
			pS->front = pS->rear;
		}
	}
	free(pS);
	pS = 0;
	return;
}

/*
用两个队列模拟入栈操作
*/
void push(PQUEUE pS1,PQUEUE pS2,int val)
{
	if(is_empty(pS2))
		en_queue(pS1, val);
	else
		en_queue(pS2, val);
}

/*
用两个队列模拟出栈操作
*/
bool pop(PQUEUE pS1,PQUEUE pS2,int *pData)
{
	if(is_empty(pS1) && is_empty(pS2))
		return false;

	int DelData;
	if(!is_empty(pS2))
	{
		int len = length(pS2);
		while(len-- > 1)
		{
			de_queue(pS2,&DelData);
			en_queue(pS1,DelData);
		}
		//将队列的最后一个元素出队,作为出栈元素
		de_queue(pS2,pData);
		return true;
	}
	if(!is_empty(pS1))
	{
		int len = length(pS1);
		while(len-- > 1)
		{
			de_queue(pS1,&DelData);
			en_queue(pS2,DelData);
		}
		//将队列的最后一个元素出队。作为出栈元素
		de_queue(pS1,pData);
		return true;
	}
}

    測试结果:



watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbnNfY29kZQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" />



版权声明:本文博客原创文章,博客,未经同意,不得转载。

时间: 2024-11-10 07:09:30

【剑指offer】两个队列实现堆栈的相关文章

和为S的连续正数序列(剑指offer) 两个个指针的应用

和为S的连续正数序列 参与人数:1005时间限制:1秒空间限制:32768K 通过比例:26.06% 最佳记录:0 ms|0K(来自  平方宁) 题目描述 小明很喜欢数学,有一天他在做数学作业时,要求计算出9~16的和,他马上就写出了正确答案是100.但是他并不满足于此,他在想究竟有多少种连续的正数序列的和为100(至少包括两个数).没多久,他就得到另一组连续正数和为100的序列:18,19,20,21,22.现在把问题交给你,你能不能也很快的找出所有和为S的连续正数序列? Good Luck!

剑指Offer - 两个链表第一个公共节点

https://www.nowcoder.com/practice/6ab1d9a29e88450685099d45c9e31e46?tpId=13&tqId=11189&tPage=2&rp=2&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking 题目描述 输入两个链表,找出它们的第一个公共结点. 代码: 注意:没有检测环状链表. /* struct ListNode { int

剑指offer——两个链表的公共节点

题目链接:输入两个链表,找出它们的第一个公共结点. 解题思路: 找出2个链表的长度,然后让长的先走两个链表的长度差,然后再一起走(因为2个链表用公共的尾部) 1 /* 2 public class ListNode { 3 int val; 4 ListNode next = null; 5 6 ListNode(int val) { 7 this.val = val; 8 } 9 }*/ 10 public class Solution { 11 public ListNode FindFir

剑指offer编程题Java实现——面试题7相关题用两个队列实现一个栈

剑指offer面试题7相关题目:用两个队列实现一个栈 解题思路:根据栈的先入后出和队列的先入先出的特点1.在push的时候,把元素向非空的队列内添加2.在pop的时候,把不为空的队列中的size()-1份元素poll出来,添加到另为一个为空的队列中,再把队列中最后的元素poll出来两个队列在栈不为空的情况下始终是有一个为空,另一个不为空的.push添加元素到非空的队列中,pop把非空队列的元素转移到另一个空的队列中,直到剩下最后一个元素,这个元素就是要出栈的元素(最后添加到队列中的元素). 1

剑指OFFER之用两个栈实现队列(九度OJ1512)

题目描述: 用两个栈来实现一个队列,完成队列的Push和Pop操作.队列中的元素为int类型. 输入: 每个输入文件包含一个测试样例.对于每个测试样例,第一行输入一个n(1<=n<=100000),代表队列操作的个数.接下来的n行,每行输入一个队列操作:1. PUSH X 向队列中push一个整数x(x>=0)2. POP 从队列中pop一个数. 输出: 对应每个测试案例,打印所有pop操作中从队列pop中的数字.如果执行pop操作时,队列为空,则打印-1 样例输入: 3 PUSH 10

《剑指Offer》附加题_用两个队列实现一个栈_C++版

在<剑指Offer>中,在栈和队列习题中,作者留下来一道题目供读者自己实现,即"用两个队列实现一个栈". 在计算机数据结构中,栈的特点是后进先出,即最后被压入(push)栈的元素会第一个被弹出(pop);队列的特点是先进先出,即第一个进入队列的元素将会被第一个弹出来.虽然栈和队列特点是针锋相对,但是两者却相互联系,可以互相转换. 在"用两个队列实现一个栈"问题中,我们用两个队列的压入和弹出来模拟栈的压入和弹出.我们通过画图的手段把抽象的问题形象化. 在上

[剑指Offer]9.用两个栈实现队列

题目 用两个栈来实现一个队列,完成队列的Push和Pop操作. 队列中的元素为int类型. 思路 用栈来模拟队列.我们首先插入一个元素a到stack1中,再压入两个元素bc,此时栈中有元素abc,其中c位于栈顶,而stack2仍然为空.我们试着删除一个元素.按照队列先进先出的原则,我们应该先删除元素a.元素a存放在stack1中且不在栈顶,因此不能直接删除.注意到stack2还未使用,我们把stack1中的元素逐个弹出并压入stack2中,stack2中的元素是cba,栈顶元素是a,我们现在可以

【Java】 剑指offer(8) 用两个栈实现队列

本文参考自<剑指offer>一书,代码采用Java语言. 更多:<剑指Offer>Java实现合集  题目 用两个栈实现一个队列.队列的声明如下,请实现它的两个函数appendTail和deleteHead,分别完成在队列尾部插入结点和在队列头部删除结点的功能. 思路 这道题较简单,自己先试着模拟一下插入删除的过程(在草稿纸上动手画一下):插入肯定是往一个栈stack1中一直插入:删除时,直接出栈无法实现队列的先进先出规则,这时需要将元素从stack1出栈,压到另一个栈stack2

LeetCode | 面试题09. 用两个栈实现队列【剑指Offer】【Python】

LeetCode 面试题09. 用两个栈实现队列[剑指Offer][Easy][Python][栈][队列] 问题 力扣 用两个栈实现一个队列.队列的声明如下,请实现它的两个函数 appendTail 和 deleteHead ,分别完成在队列尾部插入整数和在队列头部删除整数的功能.(若队列中没有元素,deleteHead 操作返回 -1 ) 示例 1: 输入: ["CQueue","appendTail","deleteHead","

【剑指offer】递归循环两种方式反转链表

转载请注明出处:http://blog.csdn.net/ns_code/article/details/25737023 本文分别用非递归和递归两种方式实现了链表的反转,在九度OJ上AC. 题目描述: 输入一个链表,反转链表后,输出链表的所有元素.(hint : 请务必使用链表) 输入: 输入可能包含多个测试样例,输入以EOF结束.对于每个测试案例,输入的第一行为一个整数n(0<=n<=1000):代表将要输入的链表的个数.输入的第二行包含n个整数t(0<=t<=1000000)