一、实现一个栈,要求实现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;
}