数据结构---栈和队列的一些面试题

一、实现一个栈,要求实现push、pop、min的时间复杂度为o(1)

1.我们用一个栈实现,偶数下标放的是普通的数据,奇数下标放的是最小数据

push:普通(偶数下标)的数据就正常放,奇数下标:当我们要放的数据大于最小值,那么我们就要更新我们的最小值,在放进去。


2.我们用两个栈实现,一个栈里面放正常数据,另一个放最小数据

push:正常栈就是就正常放,当最小栈为空的时候,就直接放,不为空的时候就要进行判断,若放的数据大于了最小栈的栈顶元素,那么就将最小栈的栈顶元素在放一遍

3.是基于第二个基础进行了改进

push:第二种方法比较浪费最小栈的空间,所以我们进行改进,假如要放的数据大于了最小栈的栈顶元素,我们就不在往最小栈里面放数据,只有在最小栈为空和要放的数据小于最小栈的栈顶时,我们在去放数据

pop:只有当普通栈和最小栈的元素一样时我们才pop最小栈


具体实现我们看看代码:

#pragma once
#include<stdio.h>
#include<stdlib.h>
//#define	TWO_ARRAY
#define	TWO_ARRAY_POOR	1


#ifdef TWO_ARRAY
//两个栈
typedef struct Minstack
{
	int array1[100];// 普通数据
	int top1;
	int array2[100];// 最小数据
	int top2;
}Minstack;
#elif TWO_ARRAY_POOR
typedef struct Minstack
{
	int array1[100];
	int top1;
	int array2[100];
	int top2;
}Minstack;
#else
//一个栈
typedef struct Minstack
{
	int array[100];
	int top;
}Minstack;
#endif

//初始化
void Init(Minstack *pStack)
{
#ifdef TWO_ARRAY
	pStack->top1 = pStack->top2 =0;
#elif TWO_ARRAY_POOR
	pStack->top1 = pStack->top2 = 0;
#else
	pStack->top = 0;
#endif
}

//入栈
void Push(Minstack *pStack, int data)
{
	int min = data;
#ifdef TWO_ARRAY
	//两个栈
	if (pStack->top2 != 0 && pStack->array2[pStack->top2 - 1] < data)
	{
		min=pStack->array2[pStack->top2 - 1];
	}
	pStack->array1[pStack->top1++] = data;
	pStack->array2[pStack->top2++] = min;
#elif TWO_ARRAY_POOR
	pStack->array1[pStack->top1++] = data;
	if (pStack->top2 == 0 || pStack->array2[pStack->top2 - 1] > data)
	{
		pStack->array2[pStack->top2++] = data;
	}

#else
	//一个栈
	if ((pStack->top != 0) && (pStack->array[pStack->top - 1] < data))
	{
		min = pStack->array[pStack->top - 1];
	}
	pStack->array[pStack->top++] = data;
	pStack->array[pStack->top++] = min;
#endif
}
//出栈
void Pop(Minstack *pStack)
{
#ifdef TWO_ARRAY
	//两个栈
	pStack->top1--;
	pStack->top2--;
#elif TWO_ARRAY_POOR
	if (pStack->array1[pStack->top1 - 1] == pStack->array2[pStack->top2 - 1])
	{
		pStack->top2--;
	}
	pStack->top1--;
#else
	//一个栈
	pStack->top-=2;
#endif
}

//栈顶元素
int Top(Minstack *pStack)
{
#ifdef TWO_ARRAY
	//两个栈
	return pStack->array1[pStack->top1-1];
#elif TWO_ARRAY_POOR
	return pStack->array1[pStack->top1-1];
#else
	//一个栈
	return pStack->array[pStack->top - 2];
#endif
}

//最小数据
int Min(Minstack *pStack)
{
#ifdef TWO_ARRAY
	//两个栈
	return pStack->array2[pStack->top2-1];
#elif TWO_ARRAY_POOR
	return pStack->array2[pStack->top2 - 1];
#else
	//一个栈
	return pStack->array[pStack->top - 1];
#endif
}

void TestMinStack()
{
	Minstack minstack;
	int array[] = { 4, 3, 5, 7, 2, 9, 0 };
	Init(&minstack);
	int i;
	for (i = 0; i < sizeof(array) / sizeof(int); i++)
	{
		Push(&minstack, array[i]);
		printf("栈顶元素:%d,min:%d\n", Top(&minstack), Min(&minstack));
	}
	for (; i < sizeof(array) / sizeof(int); i++) {
		Pop(&minstack);
		printf("栈顶元素: %d,Min: %d\n", Top(&minstack), Min(&minstack));
	}
}

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

想法:定义一个结构体里面有两个栈,一个专门用于入数据、一个专门用于出数据,将数据先入栈到栈1中,在将数据搬移到栈2,此过程是:当满足条件栈1不为空,栈2为空时,将栈1的栈顶数据先拿出来放进栈2,这样以此类推,最后再将栈2的数据pop就可以实现一个队列

具体代码如下~

这里用到了栈的相关代码,可以戳这里了解啊~

https://blog.csdn.net/Z_JUAN1/article/details/80860960


#pragma once

#include "stack1.h"
#include <stdio.h>
typedef struct SQueue{
	Stack stack1;//入数据
	Stack stack2;//出数据
}SQueue;

//初始化
void Init(SQueue *pSQ)
{
	Stack *p1, *p2;
	p1 = &(pSQ->stack1);
	p2 = &(pSQ->stack2);
	StackInit(p1);
	StackInit(p2);
}
//入栈
void Push(SQueue *pSQ, SDataType data)
{
	Stack *p1, *p2;
	p1 = &(pSQ->stack1);
	p2 = &(pSQ->stack2);
	StackPush(p1, data);
}

//出栈
void Pop(SQueue *pSQ)
{
	Stack *p1, *p2;
	p1 = &(pSQ->stack1);
	p2 = &(pSQ->stack2);
	SDataType data;

     if(StackIsEmpty(p2))
	{
		while(!StackIsEmpty(p1))
		{
			data=StackTop(p1);
			StackPop(p1);
			StackPush(p1, data);
		}
	}
		 StackPop(p2);
}

SDataType Front(SQueue *pSQ)
{
	Stack *p1, *p2;
	p1 = &(pSQ->stack1);
	p2 = &(pSQ->stack2);
	SDataType data;

	if (StackIsEmpty(p2))
	{
		while (!StackIsEmpty(p1))
		{
			data = StackTop(p1);
			StackPop(p1);
			StackPush(p1, data);
		}
	}
	return StackTop(p2);
}

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

想法:我们先将数据入到队列,然后在将数据出栈size-1个,在依次入到栈里,此时我们在出栈,方可实现


具体代码如下~

#pragma once
#include <stdio.h>

#include "queue.h"

typedef struct QStack{
	Queue queue;
} QStack;

//初始化
void Init(QStack *pQS)
{
	QueueInit(&(pQS->queue));
}

//入队列
void Push(QStack *pQS, QDataType data)
{
	QueuePush(&(pQS->queue),data);
}

//出队列
void Pop(QStack *pQS)
{
	int i;
	QDataType data;
	Queue *pQ = &(pQS->queue);
	for (i = 1; i < QueueSize(pQ); i++)
	{
		data = QueueFront(pQ);
		QueuePop(pQ);
		QueuePush(pQ, data);
	}
	QueuePop(pQ);
}

QDataType Top(QStack *pQS)
{
	int i;
	QDataType data;
	Queue *pQ = &(pQS->queue);
	for (i = 1; i < QueueSize(pQ); i++)
	{
		data = QueueFront(pQ);
		QueuePop(pQ);
		QueuePush(pQ, data);
	}
	data = QueueFront(pQ);
	QueuePop(pQ);
	QueuePush(pQ,data);
	return data;
}
void Test()
{
	QStack queue;
	Init(&queue);
	Push(&queue, 1);
	Push(&queue, 2);
	Push(&queue, 3);
	Push(&queue, 4);
	Pop(&queue);
	int b = Top(&queue);
	printf("%d\n",b);
}

四、元素出栈、入栈顺序的合法性。


#pragma once

#include<stdio.h>
#include<stdlib.h>
#include "stack1.h"

//判断元素出栈入栈顺序合法性
//前提:in out的长度要一样
//合法返回1  不合法返回0

//1.进栈序列和出栈比较    2.出栈和栈顶比较(不等和相等)
int IsValidOrder(char in[], char out[], int size)
{
	int ii = 0;
	int io = 0;
	Stack stack;
	StackInit(&stack);
	while (ii<size){
		if (in[ii] == out[io] ){
			ii++;
			io++;//直接入栈再出栈
		}
		else if (!StackIsEmpty(&stack) && out[io]==StackTop(&stack))
		{
			StackPop(&stack);
			io++;
		}
		else
		{
			StackPush(&stack,in[ii]);
			ii++;
		}
	}
	while (!StackIsEmpty(&stack))
	{
		if (out[io] != StackTop(&stack))
		{
			return 0;
		}
		StackPop(&stack);
		io++;
	}
	return 1;
}


猜你喜欢

转载自blog.csdn.net/z_juan1/article/details/80872810