解析栈和队列面试题

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

思路:

1、首先定义两个栈(s,min),栈s存放数据,栈min存放当前所有数据的最小值
2、对于栈s正常入栈,出栈就可以
3、对于栈min,当栈min为空或者入栈的数据x小于等于栈min栈顶元素的值就将x入栈;当栈s栈顶元素的值等于栈min栈顶元素的值,栈min进行出栈操作
4、取栈min栈顶元素的值即为当前的最小值

// 入栈
void Push(Stack *s, Stack *min, DataType x)
{
		StackPush(s, x);
		if (StackEmpty(min) || x <= StackTop(min))
		{
			StackPush(min, x);
		}
}

// 出栈
void Pop(Stack *s, Stack *min)
{
	if (StackTop(s) == StackTop(min))
	{
		StackPop(min);
	}
	StackPop(s);
}

// 返回最小值
int GetMin(Stack *min)
{
	if (!StackEmpty(min))
	{
		return StackTop(min);
	}
}

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

int Test_Legality(int *in, int *out, int size) // in为入栈序列数组指针,out为出栈序列数组指针,size为数组大小
{
	Stack s;
	StackInit(&s);
	int i = 0;
	int j = 0;
	for (i = 0; i < size; i++)
	{
		StackPush(&s, in[i]);
		while (!StackEmpty(&s) && StackTop(&s) == out[j])
		{
			StackPop(&s);
			j++;
		}
	}
	return StackEmpty(&s); // 当所有出栈序列元素都匹配完之后,此时栈为空,即合法;否则不合法
}

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

// 入队
void TwoStack_Queue_Push(Stack *s1, DataType x) // 入数据只在s1中入
{
	StackPush(s1, x);  
}

// 出队
void TwoStack_Queue_Pop(Stack *s1, Stack *s2)  // 出数据只在s2中出
{
	if (StackEmpty(s2)) // 当s2为空时,先把s1中的数据倒到s2中去
	{
		while (!StackEmpty(s1))
		{
			StackPush(s2, StackTop(s1));
			StackPop(s1);
		}
	}
	StackPop(s2);
}

// 返回队头元素
DataType TwoStack_Queue_Front(Stack *s1, Stack *s2)
{
	if (StackEmpty(s2))
	{
		while (!StackEmpty(s1))
		{
			StackPush(s2, StackTop(s1));
			StackPop(s1);
		}
	}
	return StackTop(s2);
}

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

思路:

1、第一次入数据时,两个队列(q1,q2)都为空,先将数据入到q2中去;之后入数据都往不为空的那个队列入,保证一个队列为空,一个队列不为空
2、出数据时,将不为空的那个队列中的前size-1个数据依次Push到为空的那个队列里,依次Pop后保留最后一个,再将其Pop掉

// 入栈
void TwoQueue_Stack_Push(Queue *q1, Queue *q2, DataType x)
{
	if (!QueueEmpty(q1)) // q1不为空,将x入到q1中去
	{
		QueuePush(q1, x);
	}
	else // q1为空,将x入到q2中去
	{
		QueuePush(q2, x);
	}
}

// 出栈
void TwoQueue_Stack_Pop(Queue *q1, Queue *q2)
{
	if (QueueEmpty(q1)) // 如果q1为空,将q2中的元素依次入到q1中(除了最后一个元素)
	{
		int size = QueueSize(q2);
		while (--size)
		{
			QueuePush(q1, QueueFront(q2));
			QueuePop(q2);
		}
		QueuePop(q2);
	}
	else // 如果q1不为空,将q1中的元素依次入到q2中(除了最后一个元素)
	{
		int size = QueueSize(q1);
		while (--size)
		{
			QueuePush(q2, QueueFront(q1));
			QueuePop(q1);
		}
		QueuePop(q1);
	}
}

// 获取栈顶元素
DataType TwoQueue_Stack_Top(Queue *q1, Queue *q2)
{
	if (!QueueEmpty(q1))
	{
		return QueueFront(q1);
	}
	else
	{
 		return QueueFront(q2);
	}
}

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

方法:奇偶栈、中间栈、头尾栈

以奇偶栈为例,具体实现如下:

  • Stack.h
#ifndef __Stack_h__
#define __Stack_h__

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <Windows.h>

#define Initsize 4 //初始存储空间
#define Increment 2 //每次增量

typedef int DataType;

typedef struct Stack
{
	DataType* _array;
	size_t _size1; // 栈1的有效数据个数
	size_t _size2; // 栈2的有效数据个数
	size_t _capacity; //总容量 
}Stack;

void StackInit(Stack* s);
void CheckCapacity(Stack* s);
void StackPush(Stack* s, DataType x, int which);
void StackPop(Stack* s, int which);
DataType StackTop(Stack* s, int which);
int StackEmpty(Stack* s, int which);
void StackPrint(Stack *s, int which);

#endif __Stack_h__
  • Stack.c
#define _CRT_SECURE_NO_WARNINGS 1

#include "Stack.h"

//初始化
void StackInit(Stack* s)
{
	assert(s);
	s->_size1 = 0;
	s->_size2 = 0;
	s->_capacity = Initsize;
	s->_array = (DataType*)malloc(Initsize*sizeof(DataType));
	if (s->_array == NULL)
	{
		perror("StackInit");
		return;
	}
	memset(s->_array, 0, s->_capacity * sizeof(DataType));
}

//扩容
void CheckCapacity(Stack* s)
{
	assert(s);
	if (s->_size1 >= s->_capacity / 2 || s->_size2 >= s->_capacity / 2)
	{
		DataType* ptr = (DataType*)realloc(s->_array, (s->_capacity + Increment)*sizeof(DataType));
		if (ptr == NULL)
		{
			perror("CheckCapacity");
		}
		else
		{
			s->_array = ptr;
			s->_capacity += Increment;
		}
	}
}

//入栈
void StackPush(Stack* s, DataType x ,int which)
{
	assert(s);
	CheckCapacity(s);
	if (which == 1)
	{
		static int i = 0; // 栈1在偶数位
		s->_array[i] = x;
		s->_size1++;
		i = i + 2;
	}
	else if (which == 2)
	{
		static int j = 1; // 栈2在奇数位
		s->_array[j] = x;
		s->_size2++;
		j = j + 2;
	}
}

//出栈
void StackPop(Stack* s, int which)
{
	assert(s);
	if (which == 1)
	{
		if (s->_size1 == 0)
		{
			printf("栈1为空\n");
		}
		else
		{
			s->_size1--;
		}
	}
	else if (which == 2)
	{
		if (s->_size2 == 0)
		{
			printf("栈2为空\n");
		}
		else
		{
			s->_size2--;
		}
	}
}

//获取栈顶元素
DataType StackTop(Stack* s, int which)
{
	assert(s);
	if (which == 1)
	{
		if (s->_size1 == 0)
		{
			printf("栈1为空\n");
			return -1;
		}
		return s->_array[((s->_size1) - 1) * 2];
	}
	else if (which == 2)
	{
		if (s->_size2 == 0)
		{
			printf("栈2为空\n");
			return -1;
		}
		return s->_array[((s->_size2) - 1) * 2 + 1];
	}
}

//判空
int StackEmpty(Stack* s, int which)
{
	assert(s);
	if (which == 1)
	{
		if (s->_size1)
		{
			return 0;
		}
		else
		{
			return 1;
		}
	}
	else if (which == 2)
	{
		if (s->_size2)
		{
			return 0;
		}
		else
		{
			return 1;
		}
	}
}

//打印
void StackPrint(Stack *s, int which)
{
	assert(s);
	if (which == 1)
	{
		if (StackEmpty(s, 1))
		{
			printf("栈1为空\n");
		}
		else
		{
			int i = 0;
			while (s->_size1--)
			{
				printf("%d ", s->_array[i]);
				i = i + 2;
			}
			printf("\n");
		}
	}
	else if (which == 2)
	{
		if (StackEmpty(s, 2))
		{
			printf("栈2为空\n");
		}
		else
		{
			int j = 1;
			while (s->_size2--)
			{
				printf("%d ", s->_array[j]);
				j = j + 2;
			}
			printf("\n");
		}
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值