实现一个栈,要求实现Push(出栈)、Pop(入栈)、Min(返回最小值)的时间复杂度为O(1)
这道题出栈和入栈都比较好求,关键在于这个返回最小值的时间复杂度,一般来说,要遍历一遍,但是这样时间复杂度就是O(n),和题意不符,这道题的做法是创建一个结构体,这个结构体中保存着入栈元素的大小,也包含着这个栈中最小的元素,然后再创建一个结构体,这个结构体是栈,入栈的时候直接压入结构体,情况如下所示:
test.c
#include"StackAndQueuelnterview.h"
#include<Windows.h>
int main()
{
Stack s;
InitStack(&s);
StackPush(&s, 5);
StackPush(&s, 5);
StackPush(&s, 6);
StackPush(&s, 2);
StackPop(&s);
StackPush(&s, 8);
StackPush(&s, 10);
StackPush(&s, 50);
//最小值应该是5
printf("Minddata is %d", StackMindata(&s));
system("pause");
return 0;
}
Stacklnterview.h
#pragma once
#include<stdio.h>
#include<assert.h>
#define MAX_SIZE 100
//封装结构体,最大100个
typedef struct NewData
{
int data;
int Mindata;
}Newdata;
typedef struct Stack
{
Newdata _arr[MAX_SIZE];//栈里放封装好的结构体
int _size;
}Stack,*PStack;
//初始化
void InitStack(PStack s);
//栈顶插入元素
void StackPush(PStack s, int data);
//出栈
void StackPop(PStack s);
//返回最小元素
int StackMindata(PStack s);
Stacklnterview.c
#include"StackAndQueuelnterview.h"
//初始化
void InitStack(PStack s)
{
assert(s);
s->_size = 0;
}
//栈顶插入元素
void StackPush(PStack s, int data)
{
assert(s);
int size = s->_size;
if (size == MAX_SIZE)
{
printf("栈满了");
return;
}
//如果栈是空的,最小的等于第一个元素的值
if (size == 0)
{
s->_arr->data = data;
s->_arr->Mindata = s->_arr->data;
s->_size++;
return;
}
if ((s->_arr + size -1)->Mindata > data)
{
(s->_arr + size)->Mindata = (s->_arr + size)->data = data;
s->_size++;
return;
}
//压入的元素大于上一个元素的Minddata
else
{
(s->_arr + size)->Mindata = (s->_arr + size-1)->Mindata;
(s->_arr + size)->data = data;
s->_size++;
}
}
//出栈
void StackPop(PStack s)
{
assert(s);
if (s->_size == 0)
{
printf("栈为空");
return;
}
s->_size--;
}
//返回最小元素
int StackMindata(PStack s)
{
assert(s);
if (s->_size == 0)
{
printf("没有元素");
return;
}
return (s->_arr + (s->_size - 1))->Mindata;
}
///////////////////////////////////////////////////////////队列/////////////////////////////////////////////////////////////////////
使用两个栈实现一个队列
思路:栈是先进后出,队列是先进先出,用两个栈来实现,先把队列的元素加到其中一个栈里,如果满了,就搬移到另外一个栈,这样栈顶元素就是队列的开始位置,以后再往进加队列元素时,先看看栈1满了没,如果没有,放到栈1中,等满了再倒入栈2,下面看图
test.c
#include"StackAndQueuelnterview.h"
//初始化队列
void QueueInit(PQueue q)
{
assert(q);
q->S1._size = 0;
q->S2._size = 0;
}
//入栈
void StackPush(Stack* s, DataType data)
{
assert(s);
if (s->_size == MAX_SIZE)
{
printf("栈满了");
return;
}
s->_arr[s->_size] = data;
s->_size++;
}
//入队列,入到栈s1
void QueuePush(PQueue q, DataType data)
{
assert(q);
if (q->S1._size == MAX_SIZE)
{
//搬移必须保证第二个队列为空
if (q->S2._size == 0)
{
while (q->S1._size != 0)
{
DataType data = StackTop(&(q->S1));
StackPop(&(q->S1));
StackPush(&(q->S2), data);
}
}
else
{
printf("s2队列不为空");
}
}
//在s1中加元素
StackPush(&(q->S1), data);
}
//返回栈顶元素
DataType StackTop(Stack* s)
{
assert(s);
if (s->_size == 0)
{
printf("栈空了");
return;
}
return s->_arr[s->_size - 1];
}
//出栈
void StackPop(Stack* s)
{
assert(s);
if (s->_size == 0)
{
printf("栈为空,操作失败!!!\n");
return;
}
s->_size--;
}
//出队列
void QueuePop(PQueue q)
{
assert(q);
//s2不为空,直接出,顶为队列头
if (q->S2._size > 0)
{
StackPop(&(q->S2));
return;
}
else
{
//如果s1也为空,队列为空
if (q->S1._size == 0)
{
printf("队为空");
return;
}
//s1不为空,将s1倒过来
else
{
while (q->S1._size != 0)
{
DataType data = StackTop(&(q->S1));
StackPop(&(q->S1));
StackPush(&(q->S2), data);
}
}
//s2的栈顶为队头
StackPop(&(q->S2));
}
}
//获取队头元素
DataType QueueFront(PQueue q)
{
assert(q);
//s1 and s2 all empty
if (q->S1._size == 0 && q->S2._size == 0)
{
printf("the queue is null");
return 0;
}
if (q->S2._size != 0)
{
return StackTop(&(q->S2));
}
else
return q->S1._arr[0];
}
//获取队尾元素
DataType QueueBack(PQueue q)
{
assert(q);
//如果s1,s2都是空的,说明队列是空的
if (q->S1._size == 0 && q->S2._size == 0)
{
printf("the queue is null");
return 0;
}
//如果s1不为空,那么队尾就是s1的栈顶,否则,就是s2的栈底
if (q->S1._size != 0)
return StackTop(&(q->S1));
else
return q->S2._arr[0];
}
StackAndQueueInterview.h
#pragma
#include<stdio.h>
#include<assert.h>
#define MAX_SIZE 9
typedef int DataType;
typedef struct Stack
{
DataType _arr[MAX_SIZE];
int _size;
}Stack;
typedef struct Queue
{
Stack S1;
Stack S2;
}Queue,*PQueue;
//初始化队列
void QueueInit(PQueue q);
//入栈
void StackPush(Stack* s, DataType data);
//入队列,入到栈s1
void QueuePush(PQueue q, DataType data);
//返回栈顶元素
DataType StackTop(Stack* s);
//出栈
void StackPop(Stack* s);
//出队列
void QueuePop(PQueue q);
//获取队头元素
DataType QueueFront(PQueue q);
//获取队尾元素
DataType QueueBack(PQueue q);
StackAndQueueInterview.c
#include"StackAndQueuelnterview.h"
//初始化队列
void QueueInit(PQueue q)
{
assert(q);
q->S1._size = 0;
q->S2._size = 0;
}
//入栈
void StackPush(Stack* s, DataType data)
{
assert(s);
if (s->_size == MAX_SIZE)
{
printf("栈满了");
return;
}
s->_arr[s->_size] = data;
s->_size++;
}
//入队列,入到栈s1
void QueuePush(PQueue q, DataType data)
{
assert(q);
if (q->S1._size == MAX_SIZE)
{
//搬移必须保证第二个队列为空
if (q->S2._size == 0)
{
while (q->S1._size != 0)
{
DataType data = StackTop(&(q->S1));
StackPop(&(q->S1));
StackPush(&(q->S2), data);
}
}
else
{
printf("s2队列不为空");
}
}
//在s1中加元素
StackPush(&(q->S1), data);
}
//返回栈顶元素
DataType StackTop(Stack* s)
{
assert(s);
if (s->_size == 0)
{
printf("栈空了");
return;
}
return s->_arr[s->_size - 1];
}
//出栈
void StackPop(Stack* s)
{
assert(s);
if (s->_size == 0)
{
printf("栈为空,操作失败!!!\n");
return;
}
s->_size--;
}
//出队列
void QueuePop(PQueue q)
{
assert(q);
//s2不为空,直接出,顶为队列头
if (q->S2._size > 0)
{
StackPop(&(q->S2));
return;
}
else
{
//如果s1也为空,队列为空
if (q->S1._size == 0)
{
printf("队为空");
return;
}
//s1不为空,将s1倒过来
else
{
while (q->S1._size != 0)
{
DataType data = StackTop(&(q->S1));
StackPop(&(q->S1));
StackPush(&(q->S2), data);
}
}
//s2的栈顶为队头
StackPop(&(q->S2));
}
}
//获取队头元素
DataType QueueFront(PQueue q)
{
assert(q);
//s1 and s2 all empty
if (q->S1._size == 0 && q->S2._size == 0)
{
printf("the queue is null");
return 0;
}
if (q->S2._size != 0)
{
return StackTop(&(q->S2));
}
else
return q->S1._arr[0];
}
//获取队尾元素
DataType QueueBack(PQueue q)
{
assert(q);
//如果s1,s2都是空的,说明队列是空的
if (q->S1._size == 0 && q->S2._size == 0)
{
printf("the queue is null");
return 0;
}
//如果s1不为空,那么队尾就是s1的栈顶,否则,就是s2的栈底
if (q->S1._size != 0)
return StackTop(&(q->S1));
else
return q->S2._arr[0];
}
判断出栈顺序是不是正确
判断的思路:一组是压栈的顺序,另一组是给的出栈的顺序,如果栈是空的,先压栈,然后和给定的出栈顺序第一个比较,如果第一个出栈的字母在栈里没有,就继续按照入栈的顺序往进入,如果有了,然后弹出,比较下一个出栈元素和栈顶是不是相等,如果不是,继续按照给定的顺序压入,以此类推,如果压到头还是没有,就说明出栈顺序是错误的!如果循环能正常结束,就说明是正确的,见图:
test.c
#include"StackAndQueuelnterview.h"
int main()
{
stack sta;
StackInit(&sta);
int a[5] = { 'a','b','c','d','e' };
int b[5] = { 'c','d','a','b','e' };
int index = 0;
int i = 0;
PrintStack(&sta);
StackInit(&sta);
for(i = 0; i < 5; i++ )
{
if ((StackEmpty(&sta) != NULL) && (StackTop(&sta) == b[i]))
StackPop(&sta);
else //压入元素
{
while (b[i] != a[index])
{
StackPush(&sta, a[index]);
index++;
if (index == 5)
{
printf("失败");
system("pause");
return;
}
}
index++;
}
}
printf("成功");
system("pause");
return 0;
}
StackAndQueuelnterview.h
#pragma once
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<assert.h>
#define T 10
#define MAX 100
typedef char DataType;
typedef struct Stack
{
DataType arr[MAX];
//int capacity;
int size;
}stack, *PStack;
// 栈的初始化
void StackInit(PStack ps);
// 入栈
void StackPush(PStack ps, DataType data);
// 出栈
void StackPop(PStack ps);
//
// 获取栈顶元素
DataType StackTop(PStack ps);
// 获取栈中元素个数
int StackSize(PStack ps);
// 检测栈是否为空
int StackEmpty(PStack ps);
void PrintStack(PStack ps);//打印栈
StackAndQueuelnterview.c
#include"StackAndQueuelnterview.h"
// 栈的初始化
void StackInit(PStack ps)
{
assert(ps);
ps->size = 0;
}
//入栈
void StackPush(PStack ps, DataType data)
{
assert(ps);
ps->arr[ps->size] = data;
ps->size++;
}
// 出栈
void StackPop(PStack ps)
{
assert(ps);
ps->size--;
}
// 获取栈顶元素
DataType StackTop(PStack ps)
{
assert(ps);
return ps->arr[ps->size - 1];
}
//获取栈中元素个数
int StackSize(PStack ps)
{
assert(ps);
return ps->size;
}
//检测栈是否为空
int StackEmpty(PStack ps)
{
if (ps->size)
return 1;
else
return 0;
}
void PrintStack(PStack ps)//打印栈
{
int i = 0;
for (; i < ps->size; i++)
{
printf("%c", ps->arr[i]);
}
}