使用两个栈实现一个队列

1、题目要求
使用两个栈实现一个队列;

2、考查点定位
  • 栈的链式结构:
通常情况下,我们使用链表来实现栈结构,有利于插入删除操作的效率,而且不用关心栈的溢出情况。
  • 队列的链式结构:
通常情况下,我们使用链表来实现队列结构,有利于插入删除操作的效率,而且不用关心队列的溢出情况。
  • 栈的操作限定:
先进后出:由top指针 单向 遍历整个栈,所以链式栈形成的过程是单链表的“ 前插法
  • 队列的操作限定:
先进先出:由front指针 单向 遍历整个队列,所以链式队列形成的过程是单链表的“ 后插法


3、设计思想
在程序的实现过程中,我经常遵循的原则是“最原始的解决之道”,即 先不考虑“最优解”,最基本的方法实现后在考虑优化,那么下面我们就用这种方法用两个栈实现一个队列:
实现的原理:栈实现队列的要求其实就是使用两个栈实现“ 先进先出 ”的操作,当然我们不能用暴力的方法把栈的数据结构修改了(修改了那也就不是栈了,哈哈)已到达先进先出的效果,那么我们怎么使用两个 先进后出 的栈达到 先进先出 的效果呢?栈的操作只能在栈顶实现插入和弹出操作, 要想把先插入的数据先取出来,得设法把先插入的数据放在栈顶就好了 ,即把栈里边的元素进行倒序,我们发现链式栈就是前插法建立的,每插一次就会翻转,那么我们可以利用第二个栈进行插入以达到翻转的效果,在第一个栈只进行插入操作,在第二栈只进行弹出操作,这样就实现了类似于队列的操作。
总结:进行两次插入栈(先进后出)的操作就可以达到队列(先进先出)的效果,插一次使原次序倒序,再插一次恢复原次序;过程如下图:
那么我们要考虑的就是插入和弹出的时机,分下面几种方法:
(1) 基本方法 :在S1中插,经过S2翻转,在S2中弹出,之后把S2倒回进行下一次插入,每次插入时要保证S2没有元素(考虑到把S2倒回S1时会打乱次序),每次弹出时后要把所有元素倒回以便下一次插入;这样就实现了最基本的队列功能。
(2) 优化方法: 我们发现S2中元素自顶向下就是正常的 出队次序, 且S2中只进行弹出操作,我们就不用把S2倒回S1,要插就在S1中插,要弹出就在S2中弹出(当S2中没有可弹出的元素时,再把S1中的元素倒过来),这样就减少了倒来倒去的操作;


4、代码实现
这里使用第二种优化方法俩实现两个栈实现一个队列的操作,下面我将按照下面步奏实现上述操作;
(1)利用前插法建立链式栈liststack:
(2)建立likequeue类封装两个链式栈liststack,设置成员函数popqueue()pushqueue()来分别实现队列的压入操作和弹出操作,其中成员函数S1insertS2()是把插入栈S1中的元素倒入S2中的操作函数,代码如下:

#include<iostream>
#include <assert.h> 
using namespace std;

struct node
{
	int data;
	node* link;
	node(const int &T, node* p = NULL){ data = T, link = p; };
};
//建立链式栈
class liststack
{
public:
	liststack();
	~liststack();
	void push(int);
	bool pop();
	node* gettop();
	bool isempty();
	void MarkEmpty();
	friend ostream& operator<<(ostream& os, liststack&TEST);
private:
	node* top;
};

liststack::liststack()
{
//不需要附加头
	top =NULL;
}

liststack::~liststack()
{
	MarkEmpty();
}

void liststack::push(int temp)
{
	if (!isempty())
	{
		node* newnode = new node(temp);
		assert(newnode!=NULL);
		newnode->link = top;
		top = newnode;
	} 
	else
	{
		node* newnode = new node(temp);
		assert(newnode != NULL);
		newnode->link = NULL;
		top = newnode;
	}
}

bool liststack::pop()
{
	if (isempty()) return false;
	
	else
	{
		node* newnode = top;
		top=top->link;
		delete newnode;
		return true;
	}
}

void liststack::MarkEmpty()
{
   	while (top!=NULL)
	{
		node* newnode = top;
		top = top->link;
		delete newnode;
	}
}

bool liststack::isempty()
{
	return top == NULL ? true: false;
}

node* liststack::gettop()
{
	return top;
}

ostream& operator <<(ostream& os, liststack&TEST)
{
	node *out = TEST.top;
	while (out)
	{
		os << out->data << endl;
		out = out->link;
	}
	return os;
};
//建立likequeue类封装两个链式栈liststack,实现队列的功能
class likequeue
{
public:
	void pushqueue(int);
	bool popqueue();
	bool S1insertS2();
	liststack S1, S2;

};

void likequeue::pushqueue(int test)
{
	S1.push(test);
}

bool likequeue::popqueue()
{
	if (S2.isempty())
	{
		S1insertS2();
	
	}
	S2.pop();
	return true;
}

bool likequeue::S1insertS2()
{
	if (S1.isempty()&&!S2.isempty()) return false;

	node* S1top = S1.gettop();
	while (S1top)
	{
		S2.push(S1top->data);
		S1top = S1top->link;
		S1.pop();
	}
	return true;
}


void main()
{
	likequeue testqueue;
	testqueue.pushqueue(1);//压入1
	testqueue.pushqueue(2);//压入2
	testqueue.popqueue();//弹出1	
	//第一次输出队列
	liststack* test = &testqueue.S2;//-------------------------更改1处		
	operator<<(cout, *test);
	system("pause");
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值