栈和队列面试题

本篇博客列举和实现了关于栈和队列的一些面试题:

1.实现一个栈,要求实现Push(出栈)、pop(入栈)、Min(返回最小值)的时间复杂度为O(1)

2.使用两个栈实现一个队列

3.使用两个队列实现一个栈

4.元素出栈,入栈的合法性。如入栈的序列(1,2,3,4,5),出栈序列为(4,5,3,2,1)

5.一个数组实现两个栈(共享栈)

实现:

1.实现一个栈,要求实现Push(出栈)、pop(入栈)、Min(返回最小值)的时间复杂度为O(1)

通过封装一个结构体,结构体中第一个元素放值,第二个元素放最小值,将结构体放入到栈中,这样返回最小值的时候从栈顶取结构体,再从结构体中取出最小值,代码实现如下:

头文件:
typedef int MSDataType;
//结构体,第一个元素放值,第二个元素放最小值
typedef struct SElem
{
	MSDataType _data;
	MSDataType _mindata;
}SElem;

//栈里放的元素为结构体SElem
typedef struct MinStack
{
	Stack _s;
}MinStack;

//初始化
void MStackInit(MinStack* ms);
//入栈
void MStackPush(MinStack* ms, MSDataType data);
//出栈
void MStackpop(MinStack* ms);
//判断栈是否为空
int MStackEmpty(MinStack* ms);
//取栈顶元素
MSDataType MStackTop(MinStack* ms);
//取出最小的元素
MSDataType GetMinData(MinStack* ms);
//栈的大小
MSDataType MStackSize(MinStack* ms);
源文件:
//栈的初始化
void MStackInit(MinStack* ms)
{
	assert(ms);
	StackInit(&ms->_s);
}
//入栈
void MStackPush(MinStack* ms, MSDataType data)
{
	assert(ms);
	SElem elem;
	//先把元素的值和最小值用data构造好
	elem._data = elem._mindata = data;
	if (!StackEmpty(&ms->_s))
	{
		//取栈里面的最小值
		MSDataType minData = GetMinData(ms);
		//若最小值比放入的数据小进行更新
		if (minData < data)
		{
			elem._mindata = minData;
		}
	}
	//将elem压栈
	StackPush(&ms->_s, elem);
}

//出栈
void MStackpop(MinStack* ms)
{
	assert(ms);
	assert(!MStackEmpty(ms));
	StackPop(&ms->_s);
}
//判断栈是否为空
int MStackEmpty(MinStack* ms)
{
	assert(ms);
	return StackEmpty(&ms->_s);
}
//取栈顶元素
MSDataType MStackTop(MinStack* ms)
{
	assert(ms);
	return StackTop(&ms->_s)._data;
}
//取栈的大小
MSDataType MStackSize(MinStack* ms)
{
	assert(ms);
	return StackSize(&ms->_s);
}
//取最小值
MSDataType GetMinData(MinStack* ms)
{
	assert(ms);
	return StackTop(&ms->_s)._mindata;
}

2.使用两个栈实现一个队列

头文件:
typedef int QDataType;
//用两个栈来封装一个队列
typedef struct QueueBy2Stack
{
	Stack _s1;
    Stack _s2;
}QueueBy2Stack;

//队列初始化
void QueueBy2StackInit(QueueBy2Stack* q);
//入队列
void QueueBy2StackPush(QueueBy2Stack* q,QDataType data);
//出队列
void QueueBy2StackPop(QueueBy2Stack* q);
//取队头
QDataType QueueBy2StackFront(QueueBy2Stack* q);
//取队尾
QDataType QueueBy2StackBack(QueueBy2Stack* q);
//队列大小
int QueueBy2StackSize(QueueBy2Stack* q);
//检测队列是否为空
int QueueBy2StackEmpty(QueueBy2Stack* q);
源文件:
//队列初始化
void QueueBy2StackInit(QueueBy2Stack* q)
{
	assert(q);
	//将两个栈初始化
	StackInit(&q->_s1);
	StackInit(&q->_s2);
}
//入队列
void QueueBy2StackPush(QueueBy2Stack* q, QDataType data)
{
	assert(q);
	//将元素放到第一个栈中
	StackPush(&q->_s1, data);
}

//出队列
void QueueBy2StackPop(QueueBy2Stack* q)
{
	assert(q);
	assert(!QueueBy2StackEmpty(q));
	//第二个栈为空时,当第一个栈非空时就将第一个栈里的数据倒到第二个栈里面
	if (StackEmpty(&q->_s2))
	{
		while (!StackEmpty(&q->_s1))
		{
			StackPush(&q->_s2, StackTop(&q->_s1));
			StackPop(&q->_s1);
		}
	}
	
	StackPop(&q->_s2);
}

//取队头
QDataType QueueBy2StackFront(QueueBy2Stack* q)
{
	assert(q);
	assert(!QueueBy2StackEmpty(q));
	//第二个栈为空时,当第一个栈非空时就将第一个栈里的数据倒到第二个栈里面
	if (StackEmpty(&q->_s2))
	{
		while (!StackEmpty(&q->_s1))
		{
			StackPush(&q->_s2, StackTop(&q->_s1));
			StackPop(&q->_s1);
		}
	}
	//第二个栈的栈顶元素就是队头
	return StackTop(&q->_s2);
}

//取队尾
QDataType QueueBy2StackBack(QueueBy2Stack* q)
{
	assert(q);
	//若第一个栈为空时,第二个栈非空,就把第二个栈里的元素倒到第一个栈中
	if (StackEmpty(&q->_s1))
	{
		while (!StackEmpty(&q->_s2))
		{
			StackPush(&q->_s1, StackTop(&q->_s2));
			StackPop(&q->_s2);
		}		
	}
	//第一个栈的栈顶就是队尾
	return StackTop(&q->_s1);
}

//大小
int QueueBy2StackSize(QueueBy2Stack* q)
{
	assert(q);
	//两个栈里面元素之和
	return StackSize(&q->_s1) + StackSize(&q->_s2);
}

//队列是否为空
int QueueBy2StackEmpty(QueueBy2Stack* q)
{
	assert(q);
	//当两个栈都为空时,队列也就为空了
	return StackEmpty(&q->_s1) && StackEmpty(&q->_s2);
}

3.使用两个队列实现一个栈

头文件:
#include"Queue.h"
typedef struct StackBy2Queueq
{
	Queue q1;
	Queue q2;
}StackBy2Queue;

void StackBy2QueueInit(StackBy2Queue* s);
void StackBy2QueuePush(StackBy2Queue* s, DataType data);
void StackBy2QueuePop(StackBy2Queue* s);
DataType StackBy2QueueTop(StackBy2Queue* s);
int StackBy2QueueSize(StackBy2Queue* s);
int StackBy2QueueEmpty(StackBy2Queue* s);
源文件
//初始化
void StackBy2QueueInit(StackBy2Queue* s)
{
	assert(s);
	QueueInit(&s->q1);
	QueueInit(&s->q2);
}
//入栈
void StackBy2QueuePush(StackBy2Queue* s, DataType data)
{
	assert(s);
	//将元素放入第一个队列中
	QueuePush(&s->q1, data);
}
//出栈
void StackBy2QueuePop(StackBy2Queue* s)
{
	assert(s);
	assert(!StackBy2QueueEmpty(s));
	//如果第一个队列非空,就只给第一个队列中留一个元素,
	//其他元素都倒到第二个队列中,取出第一个队列中的那个元素
	if (!QueueEmpty(&s->q1))
	{
		while (QueueSize(&s->q1) > 1)
		{
			QueuePush(&s->q2, QueueFront(&s->q1));
			QueuePop(&s->q1);
		}
		QueuePop(&s->q1);
	}
	//如果第一个队列为空,就就只给第二个队列中留一个元素,
	//其他元素都倒到第一个队列中,取出第二个队列中的那个元素
	else 
	{
		while (QueueSize(&s->q2) > 1)
		{
			QueuePush(&s->q1, QueueFront(&s->q2));
			QueuePop(&s->q2);
		}			
		QueuePop(&s->q2);
	}
	
}
//取栈顶元素
DataType StackBy2QueueTop(StackBy2Queue* s)
{
	assert(s);
	assert(!StackBy2QueueEmpty(s));
	//如果第一个队列非空,就取第一个队列的队头,否则取第二个队列的队头
	if (!QueueEmpty(&s->q1))
		return QueueBack(&s->q1);
	else 
		return QueueBack(&s->q2);
}

//栈的大小
int StackBy2QueueSize(StackBy2Queue* s)
{
	assert(s);
	return QueueSize(&s->q1) + QueueSize(&s->q2);
}
//是否为空
int StackBy2QueueEmpty(StackBy2Queue* s)
{
	assert(s);
	return QueueEmpty(&s->q1) && QueueEmpty(&s->q2);
}

4.元素出栈,入栈的合法性

int IsValidStack(int* In, int InSize, int* Out, int OutSize)
{
	Stack s;
	StackInit(&s);
	int InIdex = 0;
	int OutIdex = 0;

	//如果两个数组的大小都不一致,一定不合法
	if (InSize != OutSize)
		return 0;

	while (OutIdex < OutSize)
	{
		//当栈为空时或者栈顶元素不等于出栈队列时进行入栈
		while (StackEmpty(&s) || StackTop(&s) != Out[OutIdex])
		{
			if (InIdex < InSize)
				StackPush(&s, In[InIdex++]);
			//当没有元素可以入栈时,而且栈顶元素不等于出栈顺序,证明出栈顺序错误
			else
				return 0;
		}
		//当栈顶元素等于出栈顺序时进行出栈
		StackPop(&s);
		OutIdex++;
	}
	return 1;
}

5.共享栈

头文件
#define MAXSIZE 10
//利用数组实现一个共享栈,第一个栈是从前往后入栈,第二栈的元素从后往前放
typedef struct SharedStack
{
	int _array[MAXSIZE];
	int _top1;
	int _top2;
}SharedStack;


void SharedStackInit(SharedStack* s);

// 入栈 
void SharedStackPush(SharedStack* s, int data, int which);

// 出栈 
void SharedStackPop(SharedStack* s, int which);

// 获取栈顶元素 
int SharedStackTop(SharedStack* s, int which);

// 有效元素的个数 
int SharedStackSize(SharedStack* s, int which);

// 检测栈是否为空 
int SharedStackEmpty(SharedStack* s, int which);
源文件:
void SharedStackInit(SharedStack* s)
{
	s->_top1 = 0;
	s->_top2 = MAXSIZE - 1;
}

// 入栈 
void SharedStackPush(SharedStack* s, int data, int which)
{
	if (s->_top2 < s->_top1)
		return;

	if (1 == which)
		s->_array[s->_top1++] = data;
	else
		s->_array[s->_top2--] = data;
}

// 出栈 
void SharedStackPop(SharedStack* s,int which)
{
	if (SharedStackEmpty(s, which))
		return;

	if (1 == which)
		s->_top1--;
	else
		s->_top2++;
}

// 获取栈顶元素 
int SharedStackTop(SharedStack* s, int which)
{
	assert(!SharedStackEmpty(s, which));
	if (1 == which)
		return s->_array[s->_top1 - 1];
	else
		return s->_array[s->_top2 + 1];
}

// 有效元素的个数 
int SharedStackSize(SharedStack* s,int which)
{
	if (1 == which)
		return s->_top1;
	else
		return MAXSIZE-s->_top2-1;
}

// 检测栈是否为空 
int SharedStackEmpty(SharedStack* s,int which)
{
	if (1 == which)
		return 0 == s->_top1;
	else
		return MAXSIZE-1 == s->_top2;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值