栈和队列面试题

栈和队列面试题
1、实现一个栈,要求实现push(入栈),pop(出栈),Min(返回最小值)的时间复杂度为O(1)
方式1:给定两个栈,一个栈保存数据,一个栈保存最小值。取一个数据,压入数据栈中,同时向最小值栈中存入一个数据。取下一个数据,若是下一个数据小于最小值栈中的栈顶数据,则将该数据插入数据栈同时压入最小值栈中;否则压入数据栈中。

class Solution {
public:
    void push(int value) {
        StackInt.push(value);
        if(StackMin.empty())
            StackMin.push(value);
        else if(StackMin.top()<value)
            StackMin.push(StackMin.top());
        else
            StackMin.push(value);
    }
    void pop() {
        if(!StackInt.empty())
        {
            StackInt.pop();
            StackMin.pop();
        }
    }
    int top() {
        return StackInt.top();
    }
    int min() {
        return StackMin.top();
    }
private:
    stack<int> StackInt;
    stack<int> StackMin;
    
};

方式2:用一个栈实现:

(1)、压栈的时候,将一个相同的数据进栈两次,上面的那个数据表示数据,下面的元素表示最小值;继续压入下一个数据,并且用该元素与最小值进行比较:将该元素和当前最小值入栈,继续压入下面的元素……

 

 

 

实现代码:

# pragma once
# include"satck.h"
# include<assert.h>

 
//给出最小栈的操作
typedef struct MinStack
{
	Stack s;//用栈实现
}MinStack;
void MStackInit(MinStack *ms)
{
	assert(ms);
	StackInit(&ms->s);
}
//获取最小值
MSDataType GetMinData(MinStack *ms)
{
	return StackTop(&ms->s)._mindata;
}
void MStackPush(MinStack *ms, MSDataType data)
{
	//给出元素
	SElem elem;;
	elem._data = elem._mindata = data;
	if (!Stackempty(&ms->s))//栈里面有元素
	{
		MSDataType minData = GetMinData(ms);//获取最小值
		//如果最小值小于data,更新最小值中的data
		if (minData < data)
			elem._mindata = data;
	}
	StackPush(&ms->s,elem);
 }
int MSEmpty(MinStack *ms)
{
	assert(ms);
	return Stackempty(&ms->s);
}
void MStackPop(MinStack *ms)
{
	assert(ms);
	assert(!Stackempty(ms));
	StackPop(&ms->s);
}
//获取最小元素
MSDataType MStackTop(MinStack *ms)
{
	return StackTop(&ms->s)._data;
}
 
int MStackSize(MinStack *ms)
{
	return StackSize(&ms->s);
}
void TestMinStack()
{
	MinStack s;
	MStackInit(&s);
	MStackPush(&s, 2);
	MStackPush(&s, 3);
	MStackPush(&s, 4);
	MStackPush(&s, 7);
	MStackPush(&s, 5);
	printf("size=%d\n", MStackSize(&s));
	printf("top=%d\n", MStackTop(&s));
	printf("min=%d\n", MStackMinData(&s));
	MStackPop(&s);
	MStackPop(&s);
	printf("size=%d\n", MStackSize(&s));
	printf("top=%d\n", MStackTop(&s));
	printf("min=%d\n", MStackMinData(&s));
}

 

stack.h

# pragma oncee  
# include<stdio.h>  
# include<stdlib.h>  
# include<string.h>  
# include<assert.h>  
#define MAX_SIZE 10  
 
//栈里面放的元素
typedef int MSDataType;
typedef struct SElem
{
	MSDataType _data;//数据
	MSDataType _mindata;//最小值
}SElem;
typedef SElem DataTYpe;
typedef struct Stack
{
	DataTYpe _array[MAX_SIZE];//有效元素的个数  
	int _top; //栈顶元素的位置  
}Stack;

//初始化  
void StackInit(Stack *s);

//入栈  
void StackPush(Stack *s, DataTYpe data);

//出栈  
void StackPop(Stack *s);

//取栈顶元素  
DataTYpe StackTop(Stack *s);

//有效元素的个数  
int StackSize(Stack *s);

//检测栈是否为空  
int Stackempty(Stack *s);

 

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

# pragma once
# include<stdio.h>
# include<stdlib.h>
# include<string.h>
# include<assert.h>
#define MAX_SIZE 10
typedef int DataTYpe;
typedef enum{
 ADD,SUB,MUL,DIV,DATA
}OPERATE;
typedef struct Cell{
 OPERATE _op;
 int data;
}Cell;
typedef struct Stack
{
 DataTYpe _array[MAX_SIZE];//有效元素的个数
 int _top; //栈顶元素的位置
}Stack;

//初始化
void StackInit(Stack *s);

//入栈
void StackPush(Stack *s, DataTYpe data);

//出栈
void StackPop(Stack *s);

//取栈顶元素
DataTYpe StackTop(Stack *s);

//有效元素的个数
int StackSize(Stack *s);

//检测栈是否为空
int Stackempty(Stack *s);

//判断括号是否匹配
int CalRPN(Cell RPN[], int size);

 

 

 

# include<stdio.h>
# include<stdlib.h>
# include<assert.h>
# include"Stck.h"

typedef struct QueueBy2Stack
{
	Stack _s1;
	Stack _s2;
}QueueBy2Stack;
void QueueBy2StackInit(QueueBy2Stack *q)
{
	assert(q);
	StackInit(&q->_s1);
	StackInit(&q->_s2);
}
void QueueBy2StackPush(QueueBy2Stack *q, QDataType data)
{
	//入到第一个栈上,因为第一个栈为队尾
	StackPush(&q->_s1, data);
}
void QueueBy2StackPop(QueueBy2Stack *q)
{
	//如果队列中为空,则不能出队列
	if (QueueBy2StackEmpty(&q->_s2))
		return;
	//第二个队列是栈头,首先判断第二个队列中有没有元素
	if (Stackempty(&q->_s2))
	{
		//把第一个栈中的元素倒过去
		while (!Stackempty(&q->_s1))
		{
			StackPush(&q->_s2, StackTop(&q->_s1));
			StackPop(&q->_s1);
		}
	}
	StackPop(&q->_s2);
}
QDataType QueueBy2StackFront(QueueBy2Stack *q)
{
	//取对头即第二个栈的栈顶
	//如果第二个栈是空的,把元素倒过去
	//如果队列中为空,则不能出队列
	if (QueueBy2StackEmpty(&q->_s2))
		return;
	//第二个栈是队头,首先判断第二个队列中有没有元素
	if (Stackempty(&q->_s2))
	{
		//把第一个栈中的元素倒过去
		while (!Stackempty(&q->_s1))
		{
			StackPush(&q->_s2, StackTop(&q->_s1));
			StackPop(&q->_s1);
		}
	}
	return StackTop(&q->_s2);
}
QDataType QueueBy2StackBackBack(QueueBy2Stack *q)
{
	//取栈尾,看第一个栈中的数据是不是空的,如果是空的就把第二个栈中的数据倒过去
	//如果队列中为空,则不能出队列
	if (QueueBy2StackEmpty(&q->_s1))
		return;
	//第二个栈是队头,首先判断第二个队列中有没有元素
	if (Stackempty(&q->_s2))
	{
		//把第一个栈中的元素倒过去
		while (!Stackempty(&q->_s1))
		{
			StackPush(&q->_s1, StackTop(&q->_s2));
			StackPop(&q->_s2);
		}
	}
	StackPop(&q->_s1);
}
int  QueueBy2StackSize(QueueBy2Stack *q)
{
	return StackSize(&q->_s1) + StackSize(&q->_s2);
}
int QueueBy2StackEmpty(QueueBy2Stack *q)
{
	//两个栈中都为空,则队列是空的
	return Stackempty(&q->_s1) && Stackempty(&q->_s2);
}
void QueueTest()
{
	QueueBy2Stack q;
	QueueBy2StackInit(&q);
	QueueBy2StackPush(&q, 1);
	QueueBy2StackPush(&q, 2);
	QueueBy2StackPush(&q, 3);
	QueueBy2StackPush(&q, 4);
	QueueBy2StackPush(&q, 5);
	printf("size=%d\n", QueueBy2StackSize(&q));
	printf("front=%d\n", QueueBy2StackFront(&q));
	printf("back=%d\n", QueueBy2StackBack(&q));
	QueueBy2StackPop(&q);
	QueueBy2StackPop(&q);
	QueueBy2StackPop(&q);
	printf("size=%d\n", QueueBy2StackSize(&q));
	printf("front=%d\n", QueueBy2StackFront(&q));
	printf("back=%d\n", QueueBy2StackBack(&q));
}
int main()
{
	QueueTest();
	return 0;
}



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

queue.h

# pragma once
# include<stdio.h>
# include<stdlib.h>
# include<string.h>
# include<assert.h>
# include<malloc.h>
 typedef int QDataType;
typedef struct Node{
	QDataType data;
	struct  Node *_pNext;
}Node,*pNode;
typedef struct Queue{
	pNode _pHead;
	pNode _pTail;
}Queue;
void QueueInit(Queue *q);
void QueuePush(Queue *q, QDataType data);
void QueuePop(Queue *q);
pNode QueueTop(Queue *q);
pNode QueueTail(Queue *q);
int QueueEmpty(Queue *q);
int QueueSize(Queue *q);
pNode BuyNode(QDataType data);

 

 

 

源文件:

# include<stdio.h>
# include<stdlib.h>
# include<assert.h>
# include"Queue.h"
typedef int DataType;
typedef struct StackBy2Queue
{
	Queue _q1;
	Queue _q2;
}StackBy2Queue;
void StackBy2QueueInit(StackBy2Queue* s)
{
	assert(s);
	QueueInit(&s->_q1);
	QueueInit(&s->_q2);
}
void StackBy2QueuePush(StackBy2Queue* s, QDataType data)
{
	//在这里把元素入到第一个队列里面去
	QueuePush(&s->_q1, data);

}
void StackBy2QueuePop(StackBy2Queue* s)
{
	//出队列,把元素倒到q2中去,直到q1中只剩下一个元素
	//先判断栈是否为空,若是栈为空,则不能出
	if (StackBy2QueueEmpty(s))
		return;
	//判断第二个队列里面有没有数据
	if (!QueueEmpty(&s->_q1)){
		//先把队列1中的数据倒队列2中,直到队列1中只剩下一个元素为止
		while (QueueSize(&s->_q1) > 1){
			QueuePush(&s->_q2, QueueFront(&s->_q1));
			//第一个队列中的元素移走一个,即删除一个
			QueueTop(&s->_q1);
		}
		//第一个队列中只剩一个元素,移除即可
		QueuePop(&s->_q1);
	}
	//第二次出,第一个队列为空
	else
	{
		while (QueueSize(&s->_q2) > 1){
			QueuePush(&s->_q1, QueueFront(&s->_q2));
			//第二个队列中的元素移走一个,即删除一个
			QueueTop(&s->_q2);
		}
		//第二个队列中只剩一个元素,移除即可
		QueuePop(&s->_q2);
	}
}
QDataType StackBy2QueueTop(StackBy2Queue* s)
{
	//取栈顶元素,看哪个队列里面有数据
	assert(!StackBy2QueueEmpty(s));
	if (!QueueEmpty(&s->_q1))
	{
		//因为入队列优先入倒第一个队列,所以去元素也优先去第一个队列中取
		//如果第一个队列不为空,返回第一个队列的队尾
		return QueueTail(&s->_q1);
	}
	else
		return QueueTail(&s->_q2);
}
int StackBy2QueueSize(StackBy2Queue* s)
{
	return QueueSize(&s->_q1) +QueueSize(&s->_q2);
}
int StackBy2QueueEmpty(StackBy2Queue* s)
{
	return QueueEmpty(&s->_q1) && QueueEmpty(&s->_q2);
}
void Test()
{
	StackBy2Queue s;
	StackBy2QueueInit(&s);
	StackBy2QueuePush(&s, 1);
	StackBy2QueuePush(&s, 2);
	StackBy2QueuePush(&s, 3);
	StackBy2QueuePush(&s, 4);
	StackBy2QueuePush(&s, 5);
	printf("size=%d\n", StackBy2QueueSize(&s));
	printf("top=%d\n", StackBy2QueueTop(&s));
	printf("size=%d\n", StackBy2QueueSize(&s));
	printf("top=%d\n", StackBy2QueueTop(&s));
	StackBy2QueuePush(&s, 6);
	StackBy2QueuePush(&s, 7);
	printf("size=%d\n", StackBy2QueueSize(&s));
	printf("top=%d\n", StackBy2QueueTop(&s));
	StackBy2QueuePop(&s);
	StackBy2QueuePop(&s);
	printf("size=%d\n", StackBy2QueueSize(&s));
	printf("top=%d\n", StackBy2QueueTop(&s));
}
int main()
{
	Test();
	return 0;
}

 

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

int IsValidStack(int *In, int Insize, int* Out, int Outsize)
{
	int Index = 0;
	stack s;
	int Outdex = 0;
	if (Insize != Outsize)
		return 0;
	StackInit(&s);
	while (Outdex < Outsize)
	{
		while (Stackempty(&s) || StackTop(&s) != Out[Outdex])
		{
			if (Index < Insize)
				StackPush(&s, In[Index++]);
			else
				return 0;
		}
		StackPop(&s);
		Outdex++;
	}
	return 1;
}
void test()
{
	int In[] = { 1, 2, 3, 4, 5 };
	int Out[] = { 4, 5, 3, 2, 1 };
	if (!IsValidStack(In, 5, Out, 5))
		printf("入栈出栈次序非法\n");
	else
		printf("没有问题\n");
}
int main()
{
	test();
	return 0;
}

或者:

class Solution {
public:
    bool IsPopOrder(vector<int> pushV,vector<int> popV) {
        int index=0;
        if(pushV.size()==0)
            return false;
        stack<int> s;
        for(int i=0;i<pushV.size();++i)
        {
            s.push(pushV[i]);
            while(s.empty()==false&&s.top()==popV[index]&&index<popV.size())
            {
                s.pop();
                index++;
            }
        }
        if(s.empty())
            return true;
        else
            return false;
    }
};

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

 

 

法一:一个数组从左到右的一半为栈s1,从右往左为栈s2,入栈是入哪个栈就从哪边开始

 

 

法二:把第一个栈的数据放到偶数位,把第二个栈的数据放到奇数位

#define MAX_SIZE 100
typedef struct ShareStack
{
	int _array[MAX_SIZE];
	int _top1;
	int _top2;

}ShareStack;
void StackInit(ShareStack *s)
{
	s->_top1 = 0;
	s->_top2 = MAX_SIZE - 1;
}
void StackPush(ShareStack *s, int data,int which)
{
	//入栈需要保持底层有空间,top2<top1则满了
	if (s->_top2 < s->_top1)
	{
		return;
	}
	if (1 == which)
		s->array[s->_top1++] = data;//往第一个栈里面放
	else
		s->array[s->_yop2++] = data;//往第二个栈里面放
}
void StackPop(ShareStack *s,int which)
{
	if (Stackempty(s, which))
		return;
	if (1 == which)//第一个栈
		s->_top1--;
	else
		s->_top2++;
}
int StackTop(ShareStack *s)
{
	assert(!Stackempty(s,which));
	if (1 == which)
		return s->array[s->_top1 - 1];
	else
		return s->array[s->_top2 + 1];
}
int StackSize(ShareStack *s)
{
	if (1 == which)
		return s->_top1;
	else
		return MAX_SIZE-s->_top2-1;
}
int Stackempty(ShareStack *s, int which)
{
	if (1 == which)
		return s->_top1;
	else
		return MAX_SIZE-1==s->_top2;
}

 

 

(6)判断一棵二叉树最远的两个节点之间的距离(求二叉树的最大距离)

void FindMaxLen(Node *pRoot, int *maxLen)
{
	int leftHeight = 0, rightHeight = 0;
	if (NULL == pRoot)
		return;
	leftHeight = Height(pRoot->left);//左子树的高度
	rightHeight = Height(pRoot->right);//右子树的高度
	if (leftHeight + rightHeight > *maxLen)
		*maxLen = leftHeight + rightHeight;
	FindMaxLen(pRoot->left, maxLen);//在左子树中求最大的距离并更新
	FindMaxLen(pRoot->right, maxLen);//在右子树中求最大的距离并更新
}

 

 

从上往下求高度,可能会重复,我们可以采用从下往上求得方式进行优化,如下

 

 

法2:

int GetMaxLen(Node* pRoot, int *maxLen)
{
	int leftLen = 0, rightLen = 0;
	if (NULL == pRoot)
		return 0;
	leftLen = GetMaxLen(pRoot->left, maxLen);
	rightLen = GetMaxLen(pRoot->right, maxLen);
	if (leftLen + rightLen > *maxLen)
		*maxLen = leftLen + rightLen;
	return leftLen > rightLen ? leftLen + 1 : rightLen + 1;

}

 

 

 

(7)将二叉搜索树转化成排序的双向链表。要求不创建任何新的节点,只能调整树中节点指针的指向

Node *BSTreeToDList(Node *pRoot)
{
	Node *pPre = NULL;
	Node *pHead = NULL;
	if (NULL == pRoot)
		return NULL;
	//找链表的头
	while (pHead->left)
		//左子树存在
		pHead = pHead->left;
	_BSTreeToDList(pRoot,&pPre);//调整每一个节点左右指针域的指向
}
//按中序的序列调整左右指针的指向
void _BSTreeToDList(Node* pRoot,Node **pPre)
//在函数体里面要不断改变指针遍量pPre的指向,改变的结果要带出去,所以要传二级指针
{
	if (NULL == pRoot)
		return;
	//先走左子树中节点左右指针域的指向
	_BSTreeToDList(pRoot->left);
	//调整根节点左指针域以及根节点的根的前驱节点都右指针域
	//的指向(根节点的右指针域不能调整,不知道右指针域是什么。
	//多家一个参数,标记前驱节点的位置
	pRoot->left = pPre;
	if (*pPre)
		*pPre->right = pRoot;
	*pPre = pRoot;//处理结束之后标记root
		//调整右子树左右指针域的指向
	_BSTreeToDList(pRoot->right);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xuruhua

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值