码迷,mamicode.com
首页 > 其他好文 > 详细

用两个栈实现一个队列

时间:2016-05-15 20:09:11      阅读:147      评论:0      收藏:0      [点我收藏+]

标签:实现   两个栈   一个队列   

                         用两个栈实现一个队列
1、线性表分为:顺序表和链表。
栈:只允许在尾上(即是栈顶)进行插入与删除。
队列:它是在队尾插入,队头删除。
2、栈选数组(即顺序表)结构时(比选链表结构更好):因为选数组结构可以进行size++与size--,而且效率高。
     栈选链表结构:
3、队列选数组结构时:选数组结构不好,因为删除时需要整体前移,因为队列是在队头进行删除,删除了队头元素时,其后面所跟的其他元素就需要整体向前移一位。效率较低。
     队列选链表结构时:比选数组结构好,因为插入和删除元素时方便。
#include <iostream>
#include <stack>
#include <assert.h>
using namespace std;

//2、两个栈实现一个队列
//思路:当两个栈都为空时,只能做入队操作,当两个栈不都为空时,入队、出队操作都可以实现。
//      inSta主要用于入栈,outSta主要用于出栈
//过程:
//      入队:1、当outSta为空时,入队操作相当于对inSta做入栈操作(包括inSta为空和inSta不为空两种情况)
//            2、当inSta为空,outSta不为空(即上一操作为出栈,inSta转移到outSta的元素没有转移回inSta)时,此时先把outSta的所有元素出栈,
//               并按照出栈顺序入栈到inSta,然后再把此时要入队列的元素入栈到inSta
//            PS:不会出现inSta不为空,outSta不为空的情况,这种情况只会在前一操作为入队列的出队列过程中(inSta的元素除栈底元素外全部转移
//                到outSta),然后这一操作执行前outSta为空,执行后,inSta为空
//      出队:1、当inSta、outSta都为空时,队列里面无元素,无法实现出栈
//            2、当inSta不为空,outSta为空时,把inSta除栈底元素外的所有元素出栈,并按照出栈顺序入栈到outSta,把inSta的栈底元素出栈
//            3、当inSta为空,outSta不为空时,说明上一操作为出栈,inSta转移到outSta的元素没有转移回inSta,此时把outSta的栈顶元素出栈即可
//            PS:不会出现两个栈都不为空的情况,这种情况只会在前一操作为入队列的出队列时,然后这一操作执行前outSta为空,执行后,
//                Stack1为空

template<typename T>
class TwoStackForQueue
{
public:
	TwoStackForQueue()
	{
		//利用stack的构造函数完成
	}

	TwoStackForQueue(const TwoStackForQueue<T>& que)
	{
		//调用stack的赋值运算符重载/拷贝构造函数
		inSta = que.inSta;
		outSta = que.outSta;
	}

	~TwoStackForQueue()
	{
		//这儿不用做什么事情,两个栈开辟的空间由satck释放
	}

	void Push(const T& t)
	{
		if (outSta.size() == 0)       //说明上一操作为入队操作或队列此时为空
		{
			inSta.push(t);
		}
		else
		{
			//先把outSta里面的元素按其出栈顺序入栈到inSta
			while (outSta.size() != 0)
			{
				inSta.push(outSta.top());
				outSta.pop();
			}
			inSta.push(t);
		}
	}

	void Pop()
	{
		assert(inSta.size() != 0 || outSta.size() != 0);    //队列为空的情况
		if (outSta.size() == 0)
		{
			//把inSta的栈底元素留下,直接出栈它的栈底元素即可
			while (inSta.size() != 1)
			{
				outSta.push(inSta.top());
				inSta.pop();
			}
			inSta.pop();
		}
		//说明上一操作为出栈,此时直接出栈outSta的栈顶元素即可
		else
		{
			outSta.pop();
		}
	}

	T& Front()
	{
		assert(inSta.size() != 0 || outSta.size() != 0);    //队列为空的情况
		if (outSta.size() != 0)
		{
			return outSta.top();
		}
		else
		{
			//这儿不要图方便,留下inSta的栈底元素不移动,直接返回inSta的栈底元素,因为这样做的话使inSta和outSat都不为空了,
			//而上面的Push与Pop没有对这种情况进行处理
			while (inSta.size() != 0)
			{
				outSta.push(inSta.top());
				inSta.pop();
			}
			return outSta.top();
		}
	}

	T& Back()
	{
		assert(inSta.size() != 0 || outSta.size() != 0);    //队列为空的情况
		if (outSta.size() != 0)
		{
			//这儿不要图方便,留下outSta的栈底元素不移动,直接返回outSta的栈底元素,因为这样做的话使inSta和outSat都不为空了,
			//而上面的Push与Pop没有对这种情况进行处理
			while (outSta.size() != 0)
			{
				inSta.push(outSta.top());
				outSta.pop();
			}
			return inSta.top();
		}
		else
		{
			return outSta.top();
		}
	}

	bool Empty()
	{
		if (inSta.size() == 0 && outSta.size() == 0)
		{
			return true;
		}
		else
		{
			return false;
		}
	}

	size_t Size()
	{
		//要么两个栈都为空-->返回0,要么一个为空一个不为空-->返回两个栈中不为空的栈的size即可
		return inSta.size() > outSta.size() ? inSta.size() : outSta.size();
	}

	//为了测试正确性,写一个输出运算符重载
	template<typename T>
	friend ostream& operator<<(ostream& os, const TwoStackForQueue<T>& que);
private:
	stack<T> inSta;
	stack<T> outSta;
};

template<typename T>
ostream& operator<<(ostream& os, const TwoStackForQueue<T>& que)
{
	TwoStackForQueue<T> coutque(que);
	os << "Queue: ";
	//根据入队序列输出 inSta栈顶-->最后入队的元素    outSta-->最先入队的元素
	//所以先把元素都先入栈到outSta,每次输出outSta的栈顶元素,并把它出栈,直到outSta里面没有元素即可
	if (coutque.inSta.size() > 0)
	{
		while (coutque.inSta.size() > 0)
		{
			coutque.outSta.push(coutque.inSta.top());
			coutque.inSta.pop();
		}
	}
	while (coutque.outSta.size() > 0)
	{
		os << coutque.outSta.top() << "  ";
		coutque.outSta.pop();
	}
	os << "NULL";
	return os;
}

void Test()
{
	TwoStackForQueue<int> que;
	que.Push(0);
	que.Push(5);
	que.Push(4);
	que.Push(1);
	que.Push(2);
	que.Push(3);
	cout << que << endl;


	que.Pop();
	que.Pop();
	cout << que << endl;


	cout << que.Front() << endl;
	cout << que.Back() << endl;
	cout << que.Empty() << endl;
	cout << que.Size() << endl;
}

int main()
{
	Test();
	return 0;
}
//优化版一

//2、两个栈实现一个队列
//思路:当两个栈都为空时,只能做入队操作,当两个栈不都为空时,入队、出队操作都可以实现。
//      inSta只用于入栈,outSta只用于出栈
//过程:
//      入队:不管outSta是否为空,都直接把元素入栈到inSta
//      出队:1、当inSta、outSta都为空时,队列里面无元素,无法实现出栈
//            2、当outSta为空时,把inSta除栈底元素外的所有元素出栈,并按照出栈顺序入栈到outSta,把inSta的栈底元素出栈
//            3、当outSta不为空时,说明上一操作为出栈,此时把outSta的栈顶元素出栈即可

template<typename T>
class TwoStackForQueue
{
public:
	TwoStackForQueue()
	{
		//利用stack的构造函数构造inSta与outSta即可
	}

	TwoStackForQueue(const TwoStackForQueue& que)
	{
		inSta = que.inSta;
		outSta = que.outSta;
	}

	~TwoStackForQueue()
	{
		//inSta和outSta空间的释放由stack类来完成
	}

	void Push(const T& t)
	{
		inSta.push(t);
	}

	void Pop()
	{
		assert(inSta.size() != 0 || outSta.size() != 0);    //队列为空的情况
		if (outSta.size() == 0)
		{
			//说明此时是第一次执行出对列或之前outSta里面的数据全部被出栈了
			while (inSta.size() != 1)
			{
				outSta.push(inSta.top());
				inSta.pop();
			}
			inSta.pop();
		}
		//说明之前留在outSta里面的元素没有被全部出栈
		else
		{
			outSta.pop();
		}
	}

	T& Front()
	{
		assert(inSta.size() != 0 || outSta.size() != 0);    //队列为空的情况
		if (outSta.size() != 0)
		{
			return outSta.top();
		}
		else
		{
			//当outSta为空时,说明队首元素即是inSta的栈底元素,返回它即可
			while (inSta.size() != 1)
			{
				outSta.push(inSta.top());
				inSta.pop();
			}
			return inSta.top();
		}
	}

	T& Back()
	{
		assert(inSta.size() != 0 || outSta.size() != 0);    //队列为空的情况
		if (inSta.size() != 0)
		{
			return inSta.top();
		}
		else
		{
			//当inSta为空时,说明队尾元素即是outSta的栈底元素,返回它即可
			while (outSta.size() != 1)
			{
				inSta.push(outSta.top());
				outSta.pop();
			}
			return outSta.top();
		}
	}

	bool Empty()
	{
		if (inSta.size() == 0 && outSta.size() == 0)
		{
			return true;
		}
		else
		{
			return false;
		}
	}

	size_t Size()
	{
		//返回两个栈的元素个数和
		return inSta.size() + outSta.size();
	}

	//为了测试正确性,写一个输出运算符重载
	template<typename T>
	friend ostream& operator<<(ostream& os, const TwoStackForQueue<T>& que);
private:
	stack<T> inSta;
	stack<T> outSta;
};

template<typename T>
ostream& operator<<(ostream& os, const TwoStackForQueue<T>& que)
{
	TwoStackForQueue<T> coutque(que);
	os << "Queue: ";
	//根据入队序列输出 inSta不为空:inSta栈顶-->最后入队的元素   outSta不为空:outSta栈顶-->最先入队的元素
	while (coutque.outSta.size() > 0)
	{
		os << coutque.outSta.top() << "  ";
		coutque.outSta.pop();
	}
	while (coutque.inSta.size() > 0)
	{
		coutque.outSta.push(coutque.inSta.top());
		coutque.inSta.pop();
	}
	while (coutque.outSta.size() > 0)
	{
		os << coutque.outSta.top() << "  ";
		coutque.outSta.pop();
	}
	os << "NULL";
	return os;
}

void Test()
{
	TwoStackForQueue<int> que;
	que.Push(0);
	que.Push(5);
	que.Push(4);
	que.Push(1);
	que.Push(2);
	que.Push(3);
	cout << que << endl;


	que.Pop();
	que.Pop();
	cout << que << endl;


	cout << que.Front() << endl;
	cout << que.Back() << endl;
	cout << que.Empty() << endl;
	cout << que.Size() << endl;
}

int main()
{
	Test();
	return 0;
}

本文出自 “10911544” 博客,请务必保留此出处http://10921544.blog.51cto.com/10911544/1773535

用两个栈实现一个队列

标签:实现   两个栈   一个队列   

原文地址:http://10921544.blog.51cto.com/10911544/1773535

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!