转载请注明出处: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" alt="" />



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

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

  1. 剑指 Offer 59 - II. 队列的最大值--滑动窗口的建模+Deque的基本使用(常用方法)

    剑指 Offer 59 - II. 队列的最大值 题目链接 package com.walegarrett; /** * @Author WaleGarrett * @Date 2020/12/3 1 ...

  2. 剑指Offer 两个链表的第一个公共结点

    题目描述 输入两个链表,找出它们的第一个公共结点.   思路: 题目说的很笼统,应该是有2个链表,找出公共点,第一个公共点后面的链表是共同所有的.可以用map做,直接检测map里有没有出现这个节点. ...

  3. 剑指Offer——两个链表的第一个公共结点

    题目描述: 输入两个链表,找出它们的第一个公共结点. 分析: 设置两个指针,分别从两个链表的头部开始往后遍历. 谁遍历完自己本身的,就从另一个链表开始遍历,这样大家到达第一个公共结点的时候便会相遇. ...

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

    https://www.nowcoder.com/practice/6ab1d9a29e88450685099d45c9e31e46?tpId=13&tqId=11189&tPage= ...

  5. 用js刷剑指offer(两个链表的第一个公共结点)

    题目描述 输入两个链表,找出它们的第一个公共结点. 牛客网链接 js代码 /*function ListNode(x){ this.val = x; this.next = null; }*/ fun ...

  6. 剑指offer计划27(栈与队列困难)---java

    1.1.题目1 剑指 Offer 59 - I. 滑动窗口的最大值 1.2.解法 解题思路:(来自作者bigbeats) 相当于维护一个最大队列(队头元素最大,向队尾非严格递减) 在未形成窗口前,先构 ...

  7. 剑指offer二刷(精刷)

    剑指 Offer 03. 数组中重复的数字 题目描述 在一个长度为 n 的数组里的所有数字都在 0 到 n-1 的范围内.数组中某些数字是重复的,但不知道有几个数字是重复的,也不知道每个数字重复几次. ...

  8. LeetCode:“剑指 Offer”

    LeetCode:"剑指 Offer" 刷题小菜鸡,花了几天时间做了一遍 LeetCode 上给出的 "剑指 Offer" 在此做一下记录 LeetCode主页 ...

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

    在<剑指Offer>中,在栈和队列习题中,作者留下来一道题目供读者自己实现,即"用两个队列实现一个栈". 在计算机数据结构中,栈的特点是后进先出,即最后被压入(push ...

  10. 《剑指offer》用两个栈实现队列

    本题来自<剑指offer> 用两个栈实现队列 题目: 用两个栈来实现一个队列,完成队列的Push和Pop操作. 队列中的元素为int类型. 思路: 队列定义:先进先出 栈定义:先进后出 要 ...

随机推荐

  1. 基于FPGA的红外遥控解码与PC串口通信

    基于FPGA的红外遥控解码与PC串口通信 zouxy09@qq.com http://blog.csdn.net/zouxy09 这是我的<电子设计EDA>的课程设计作业(呵呵,这个月都拿 ...

  2. 怎样高速正确的安装 Ruby, Rails 执行环境

    对于新入门的开发人员,怎样安装 Ruby, Ruby Gems 和 Rails 的执行环境可能会是个问题,本页主要介绍怎样用一条靠谱的路子高速安装 Ruby 开发环境. 次安装方法相同适用于产品环境! ...

  3. C语言信号学习笔记

    在C语言中,对于错误有很多处理方式.然而,今天学习了信号处理,感觉这种处理方式十分灵活,特此记录. 关于信号处理的函数包含于头文件<signal.h>中.所谓的信号,多指出乎程序员意料的行 ...

  4. Delphi基础Write写入结构体到文件(使用 file of myrecord就行了,真简单)

    program WriteStruct; {$APPTYPE CONSOLE} uses SysUtils; //写入结构体 type TCustomer = record ID: ]; Code: ...

  5. hdu3068之manacher算法+详解

    最长回文 Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submi ...

  6. VSTO学习笔记(七)基于WPF的Excel分析、转换小程序

    原文:VSTO学习笔记(七)基于WPF的Excel分析.转换小程序 近期因为工作的需要,要批量处理Excel文件,于是写了一个小程序,来提升工作效率. 小程序的功能是对Excel进行一些分析.验证,然 ...

  7. hdu1428之spfa+dfs

    漫步校园 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submi ...

  8. DataTable数据转换为实体

    我们在用三层架构编写软件时,常常会遇到例如以下问题,就是三层之间的參数传递问题:假设我们在D层查询出数据是DataTable类型的,那么我们在B层甚至U层使用这条数据时,就要用DataTable类型来 ...

  9. 【IOS实例小计】今日开贴,记录我的ios学习生涯,留下点滴,留下快乐,成荫后人。

    今天开贴来记录自己的ios学习过程,本人目前小白一个,由于对ios感兴趣,所以开始学习,原职java程序,呵呵,勿喷. 本次的[ios实例小计]主要参考一文http://blog.sina.com.c ...

  10. 全然符合package.json在CommonJS中的规范

    众所周知,package.json是CommonJS规定的用来描写叙述包的文件,全然符合规范的package.json文件应该含有一下字段. name:包的名称,必须是唯一的.由小写英文字母.数字和下 ...