以空间换时间--Google一道关于堆栈操作的面试题

一 题目:设计栈的数据结构,操作有入栈push,出栈pop,求栈中最小元素min,要求这三个操作的时间复杂度都是O(1)

二 求解思路:此题关键是设计min操作,使得时间复杂度是O(1),为此在设计好的堆栈数据结构中引入辅助栈,为节省空间开销,辅助栈中存放“最小元素”地址序列

比如:有一组数据4,3,10,2,8那么

当4入栈时

4                        0

栈                     辅助栈     

当3入栈时

3                        1

4                        0

栈                     辅助栈     

当10入栈时

10

3                        1

4                        0

栈                     辅助栈     

当2入栈时

2

10                      3

3                        1

4                        0

栈                     辅助栈     

当8入栈时

8

2

10                      3

3                        1

4                        0

栈                     辅助栈     

当8出栈时

2

10                      3

3                        1

4                        0

栈                     辅助栈     

当2出栈时

10                     

3                        1

4                        0

栈                     辅助栈  

当10出栈时                 

3                        1

4                        0

栈                     辅助栈 

当3出栈时                 

4                        0

栈                     辅助栈

当4出栈时                 

栈                     辅助栈

也就是说当某个元素入栈时,比较它是不是小于辅助栈栈顶元素(指针)指向的元素,   如果小于,那么将这个元素的地址压入辅助栈

当弹出元素时,比较这个元素的地址是不是和辅助栈栈顶元素相同,如果相同,那么将辅助栈栈顶元素弹出

三 代码

/*
This is a free Program, You can modify or redistribute it under the terms of GNU
*Description:以空间换时间,谷歌一道关于堆栈操作的面试题
*Language: C++
*Development Environment: VC6.0
*Author: Wangzhicheng
*E-mail: 2363702560@qq.com
*Date: 2012/11/14
*/

/*
*某个元素入栈时,比较它是不是小于辅助栈栈顶元素(指针)指向的元素,
*如果小于,那么将这个元素的地址压入辅助栈
*当弹出元素时,比较这个元素的地址是不是和辅助栈栈顶元素相同,如果相同,那么将辅助栈栈顶元素弹出
*/
#include <iostream>
#include <cstdlib>
#include <iomanip>
#include <stack>
#include <ctime>
using namespace std;

/*
*向前引用
*/
template<class Type>
class LinkedStack;
/*
*链表结点类
*/
template<class Type>
class LinkNode {
	private:
		Type data;
		LinkNode<Type> *next;
	public:
		friend class LinkedStack<Type>;
		LinkNode<Type>() {
			data=NULL;
			next=0;
		}
		LinkNode<Type>(const Type &e,LinkNode<Type> *link=0) {
			data=e;
			next=link;
		}
		LinkNode<Type>(const LinkNode<Type> &Node) {
			data=Node.getData();
			next=Node.getNext();
		}
		LinkNode<Type> & operator=(const LinkNode<Type> &Node) {
			data=Node.getData();
			next=Node.getNext();
			return *this;
		}
		bool operator<(const LinkNode<Type> &Node) {
			return data<Node.getData();
		}
		const Type&  getData()  {
			return data;
		}
		void setData(const Type &e) {
			data=e;
		}
		LinkNode<Type> * getNext() const {
			return next;
		}
		void setNext(LinkNode<Type> *p) {
			next=p;
		}
		
};
/*
*链栈类
*@top:栈顶指针
*@assistant:辅助栈,辅助栈中存放着链栈中"最小元素"地址序列
*/
template<class Type>
class LinkedStack {
	private:
		LinkNode<Type>*top;
		stack<LinkNode<Type>*>assistant;
	public:
		LinkedStack() {                        //构造函数
			top=new LinkNode<Type>;
		}
		~LinkedStack() {                       //析构函数,将栈清空
			while(!empty()) {
				pop();
			}
			delete top;
			top=0;
		}
		void push(const Type &e) {             //入栈函数
			LinkNode<Type> *p=new LinkNode<Type>(e);
			if(!p) {
				cerr<<"内存分配失败,程序退出!"<<endl;
				exit(1);
			}
			p->next=top->next;
			top->next=p;
			/*
			*此时入栈之前栈为空,将链栈当前元素的指针压入辅助栈
			*/
			if(top->next->next==0) {       
				assistant.push(top->next);
			}
			/*
			*此时链栈至少有两个元素
			*比较当前的链栈顶元素和辅助栈的栈顶元素指向的值
			*如果当前栈顶元素小于辅助栈的栈顶元素指向的值,将将链栈当前元素的指针压入辅助栈
			*/
            else {                               
				if(peek()<assistant.top()->getData()) {  
					assistant.push(top->next);
				}
			}
		}
		const Type & peek() const {           //返回栈顶元素     
			if(empty()==true) {
				return NULL;
			}
			return top->next->data;
		}
		bool empty() const {                  //判断栈是否为空
			return top->next==0;
		}
		void pop() {                          //出栈函数
			LinkNode<Type> *pre=top->next;    //获取栈顶元素的指针s      
			if(empty()==true) {
				cerr<<"堆栈已空!"<<endl;
				return;
			}
			LinkNode<Type>*p=top->next;
			top->next=p->next;
			delete p;
			/*
			*如果被弹出的元素是辅助栈栈顶元素指向的值
			*那么将辅助栈栈顶元素弹出
			*/
			if(assistant.empty()==false && pre==assistant.top()) {        
				assistant.pop();
			}
		}
		bool min(Type &value) {
			if(assistant.empty()==false) {
				value=assistant.top()->getData();
				return true;
			}
			else {
				cerr<<"栈已空!"<<endl;
				return false;
			}
		}
		void show() {
			LinkNode<Type> *p=top->next;
			int i=0;
			while(p) {
				cout<<p->getData()<<setw(4)<<" ";
				i++;
				if(i%10==0) cout<<endl;
				p=p->next;
			}
			cout<<endl;
		}
};
void main() {
	LinkedStack<int>stack;
	srand(unsigned(time(0)));
	int i;
	int e;
	int N=30;
	for(i=1;i<=N;i++) {           //随机生成N个整数压入栈
		e=(rand()%N)+2;
		stack.push(e);
	}
	int min;
	cout<<"原始栈中元素是:"<<endl;
	stack.show();
	cout<<"最小元素是:";
	if(stack.min(min)) cout<<min<<endl;
	cout<<"---------------------------------"<<endl;
	for(i=1;i<=N/2;i++) {        //弹出一半元素
		stack.pop();
	}
	cout<<"弹出一半后,栈中元素是:"<<endl;
	stack.show();
	cout<<"---------------------------------"<<endl;
	cout<<"最小元素是:";
	if(stack.min(min)) cout<<min<<endl;
}


 

四 测试

屏幕输出:

  

    

   

 

 

 

 

 

Python网络爬虫与推荐算法新闻推荐平台:网络爬虫:通过Python实现新浪新闻的爬取,可爬取新闻页面上的标题、文本、图片、视频链接(保留排版) 推荐算法:权重衰减+标签推荐+区域推荐+热点推荐.zip项目工程资源经过严格测试可直接运行成功且功能正常的情况才上传,可轻松复刻,拿到资料包后可轻松复现出一样的项目,本人系统开发经验充足(全领域),有任何使用问题欢迎随时与我联系,我会及时为您解惑,提供帮助。 【资源内容】:包含完整源码+工程文件+说明(如有)等。答辩评审平均分达到96分,放心下载使用!可轻松复现,设计报告也可借鉴此项目,该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的。 【提供帮助】:有任何使用问题欢迎随时与我联系,我会及时解答解惑,提供帮助 【附带帮助】:若还需要相关开发工具、学习资料等,我会提供帮助,提供资料,鼓励学习进步 【项目价值】:可用在相关项目设计中,皆可应用在项目、毕业设计、课程设计、期末/期中/大作业、工程实训、大创等学科竞赛比赛、初期项目立项、学习/练手等方面,可借鉴此优质项目实现复刻,设计报告也可借鉴此项目,也可基于此项目来扩展开发出更多功能 下载后请首先打开README文件(如有),项目工程可直接复现复刻,如果基础还行,也可在此程序基础上进行修改,以实现其它功能。供开源学习/技术交流/学习参考,勿用于商业用途。质量优质,放心下载使用。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值