和左神一起练算法:1.实现一个特殊的栈,在实现栈的基本功能的基础上,在实现返回栈中最小的元素的操作 2.如何仅用队列结构实现栈结构,如何仅用栈结构实现队列结构*

本文探讨了在保持O(1)时间复杂度下,如何使用两个栈实现带有getmin功能的特殊栈,并讨论了两种不同的实现方式。此外,还介绍了如何仅用队列结构实现栈的功能,以及如何仅用栈结构实现队列的功能。

实现一个特殊的栈,在实现栈的基本功能的基础上,在实现返回栈中最小的元素的操作。
要求:
1.pop,push,getmin,操作的时间复杂度都是0( 1 );
2.设计栈的类型可以使用现成的栈的结构。

#include<iostream>
#include<stack>
#include<time.h>
using namespace std;
//template<class T>
class stack1
{
public:
 	stack1()
	 {}
	 ~stack1()
 	{}
 	void push(int num)               //压入元素
 	{
  		if (p1.size() == 0)
 		{
  			 this->p1.push(num);
  			 this->p2.push(num);
  		}
  		else
  		{
  			 this->p1.push(num);
  			 push1(num);
  		}
	 }
 	void push1(int num)       //p2压入规则
 	{
 		 if (p2.top() > num)
  		{
   			p2.push(num);
  		}
  		else
  		{
   			p2.push(p2.top());
  		}
 	}
 	void pop()
	 {
 		 if (p1.size() == 0)
  		{
   			cout << "栈已空,无法弹出" << endl;
  		}
  		p1.pop();
	  	p2.pop();
	 }
 	int get_min()
 	{
 		 if (p2.size() == 0)
  		{
   			cout << "栈已空,无法弹出" << endl;
  		}
  		return p2.top();
 	}
 	int top()
 	{
  		if (p1.size() == 0)
  		{
   			perror("已空");
  		}
  		p2.top();
  		return p1.top();
 	} 
private:
 	stack<int>p1;
 	stack<int>p2;
};
int main()
{
 	srand((unsigned int)time(NULL));
 	stack1 v;
 	for (int i = 0; i < 10; ++i)
 	{
 		 v.push(rand() % 5);
 	}
 	for (int i = 0; i < 10; ++i)
 	{ 
 		 cout << v.get_min() ;
 		 cout << v.top() << endl;
  		v.pop();
 	}
 	return 0;
}

这里主要是讲的是getmin()设计两个栈,一个栈用来负责普通的压入,弹出,查看。另外一个栈负责记录现在栈里面的最小的值,也就是说当给专门负责的栈里面压入一个元素时,当压入的这个元素是第一个元素的时候,那么就在负责 记录的那个栈里面压入这个元素,如果是第二个元素的时候,那么就比较这个栈里面栈顶的元素和栈里面的第一个元素的大小,把较小者继续压入栈,以此类推,也就是第二栈专门用来记录第一个栈中已有元素的最小的元素,如果想知道第一个栈里面的元素的最小元素是什么那么久直接将第二个栈的栈顶的元素弹出。

这个是第一种写法,这种写法能废一点空间,也就是说两个栈的空间一样大。

在这里插入图片描述
第二种写法就是 能比第一种省一点空间也就是这个样子的
在这里插入图片描述
第二种方法也就说在第一个栈压入新元素的时候那么第二个栈,就拿压入的新元素和自己的顶部元素比较,如果小的话那么自己这边也压入,如果大的话就不压入,如果相等的话重复压入。

#include<iostream>
#include<stack>
using namespace std;
class stack1
{
public:
 	stack1()
 	{}
 	~stack1()
 	{}
 	void push(int num)               //压入元素
 	{
 	 	if (p1.size() == 0)
 	 	{
   			this->p1.push(num);
   			this->p2.push(num);
  		}
  		else
  		{
   			this->p1.push(num);
   			push1(num);
  		}
 	}
 	void push1(int num)       //p2压入规则
 	{
  		if (p2.top() >= num)   //堆顶元素大于或者等于新压入的元素,压入
  		{
   			p2.push(num);
  		}
  		else       //否则不做任何处理
  		{}
 	}
 	void pop()           //弹出
 	{
  		if (p1.size() == 0)
  		{
   			cout << "栈已空,无法弹出" << endl;
  		}
  		pop1();
  		p1.pop(); 
 	}
 	void pop1()
 	{
  		if (p1.top() > p2.top())
  		{
  		}
  		if (p1.top() == p2.top())
  		{
   			p2.pop();
  		}
 	}
 	int get_min()
 	{
  		if (p2.size() == 0)
  		{
   			cout << "栈已空,无法弹出" << endl;
  		}
  		return p2.top();
 	}
 	int top()
 	{
  		if (p1.size() == 0)
  		{
   			perror("已空");
  		}
  		p2.top();
  		return p1.top();
 	}
private:
 	stack<int>p1;
 	stack<int>p2;
};
int main()
{
 	stack1 v;
  	v.push(3);
  	v.push(5);
  	v.push(1);
  	v.push(2);
  	v.push(1);
 	for (int i = 0; i < 5; ++i)
 	{
  		cout << v.get_min();
  		cout << v.top() << endl;
  		v.pop();
 	}
 	return 0;
}

2.何如仅用队列结构实现栈结构
两个队列,在需要弹出的时候就把第一个栈除最后一个压入的元素外,其他元素都压到另外一个栈里面去,然后把第一个栈剩的那一个元素弹出来,然后再把栈交换回去,也可以每次在弹出的时候再交换,都可以。

//用队列实现栈基本功能
#include<iostream>
using namespace std;
#include<queue>
class MYstack
{
public:
 	void push1(int num)  //插入
 	{
  		this->p1.push(num);
 	}
 	void pop()   //弹出
 	{
  		while (p2.size() > 0)//复用,完了之后再将p2搬移回p1
  		{
   			p1.push(p2.front());
   			p2.pop();
  		}
  		while (p1.size() > 1)      //搬移直到p1只剩下一个元素
  		{
   			p2.push(p1.front());   //将第一个队列的首元素搬移到第二个队列
   			p1.pop();//每次搬移完之后把这个元素弹走
  		}
  		p1.pop();    //然后将队中唯一元素弹掉
 	}
 	int top()   //查看
 	{
  		while (p2.size() > 0)
  		{
   			p1.push(p2.front());
   			p2.pop();//每次搬移完元素之后不要忘记弹走元素
  		}
  		return p1.back();
 	}
private:
 	queue<int>p1;
 	queue<int>p2;
};
int main()
{
 	MYstack v;
 	v.push1(1);
 	v.push1(2);
 	v.push1(3);
	v.push1(4);
 	v.push1(5);
 	for (int i = 0; i < 5; i++)
 	{
  		cout << v.top() << endl;
  		v.pop();
 	}
 	return 0;
}

while (p2.size() > 0)
{
p1.push(p2.front());
p2.pop();//每次搬移完元素之后不要忘记弹走元素
}
也可以直接使用swap()函数交换swap(p1,p2);

如何仅用栈结构实现队列结构
两个栈,一个栈负责压入,另外一个栈用来弹出,在弹出的时候,将负责压入的栈按照栈的原则依次压入负责弹出的栈然后再依次弹出。
有两个注意事项:
1.每次无论弹出几个数字,一定要把第一个栈的全部元素全部压入第二个栈再从第二个栈弹出。
2只有第二个栈为空才可以往第一个栈中压入数字,把数字再还原回第一个栈之后才可以压入

相当于经历压入操作之后,元素都在1号栈,
在进行查看操作结束后元素都在2号栈
在进行弹出操作结束之后元素也都在1号栈

#include<iostream>
#include<stack>
using namespace std;
class MYqueue
{
public:
 	void mypush(int num)         //压入,压入的话都是对第一个栈进行压入
 	{
  		if (p2.size() == 0)     //正如注意事项所说,只有在第二个栈空的时候,才可以对第一个栈进行压入
  		{
   			this->p1.push(num);
   			return;
  		}
  		while (p2.size() > 0)   //否则的话就要将第二个栈的元素重新导入第一个栈之后才可以进行压入操作
  		{
   			p1.push(p2.top());
   			p2.pop();
  		}
  		p1.push(num);   //搬移完之后再进行压入
 	}
 	int mytop()    //查看队列顶部元素,因为在查看之前元素都在一号栈
 	{
  	 	while (p1.size() > 0)   //这里假如是一号栈有元素,则搬完之后再查看二号栈元素
   		{
    			p2.push(p1.top());
    			p1.pop();
   		}
   		return p2.top();//然后再由p2进行查看
 	}
 	void mypop()    //弹出
 	{
  		while (p1.size() > 0)
  		{
   			p2.push(p1.top());
   			p1.pop();
  		}
  	 	p2.pop();
 	}
 	int back()   //查看尾部元素
 	{
  		if (p2.size() > 0)
  		{
   			p1.push(p2.top());
   			p2.pop();
  		}
  		return p1.top();
 	}
private:
 	stack<int>p1;
 	stack<int>p2;
};
int main()
{
 	MYqueue v;
 	v.mypush(1);
 	cout << v.mytop() << endl;
 	v.mypop();
 	v.mypush(2);
 	cout << v.mytop() << endl;
 	v.mypop();
 	v.mypush(3);
 	cout << v.mytop() << endl;
 	v.mypop();
 	v.mypush(4);
 	cout << v.mytop() << endl;
 	v.mypop();
 	v.mypush(5);
 	cout << v.mytop() << endl;
 	v.mypop();
 	////////////////////////////////////////////////////
 	v.mypush(1);
 	v.mypush(2);
 	v.mypop();
 	v.mypush(3);
 	v.mypush(4);
 	v.mypop();
 	for (int i = 0; i < 2; ++i)
 	{
 		 cout << v.mytop();
 		 v.mypop();	
 	}
 	return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值