实现一个栈,要求实现push,pop,min的时间复杂度最低。
思路是:入栈时一次入两个元素,第一个元素是要入栈的元素,第二个元素是min,min为当前栈的最小元素与插入元素的较小的那个元素。出栈时每次出两个,保证栈的结构仍然是先进后出。取栈顶元素时,也能保证每次取到的都是栈里最小的元素。
//实现一个栈要求,出栈入栈,返回最小值的时间复杂度是O(1)
typedef struct min_stack
{
SeqStack stack;
}min_stack;
void MinStackPush(min_stack* s,StackType value)
{
if(s==NULL)
{
return;
}
StackType n;
StackType min=value;
int ret=SeqStackTop(&s->stack,&n);
if(ret==0)
{
SeqStackPush(&s->stack,value);
SeqStackPush(&s->stack,min);
return;
}
if(value>n)
{
min=n;
}
SeqStackPush(&s->stack,value);
SeqStackPush(&s->stack,min);
}
void MinStackPop(min_stack* s)
{
if(s==NULL)
{
return;
}
if(s->stack.size==0)
{
return;
}
SeqStackPop(&s->stack);
SeqStackPop(&s->stack);
}
int MinStackTop(min_stack* s,StackType* value)
{
if(s==NULL)
{
return 0;
}
if(s->stack.size==0)
{
return 0;
}
SeqStackTop(&s->stack,value);
return 1;
}
测试代码:
void TestMin()
{
min_stack s;
StackType value;
SeqStackInit(&s.stack);
MinStackPush(&s,'d');
int ret=MinStackTop(&s,&value);
printf("ret expect 1,actual %d\n",ret);
printf("top expect d,actual %c\n",value);
MinStackPush(&s,'c');
MinStackPush(&s,'b');
MinStackPush(&s,'a');
ret=MinStackTop(&s,&value);
printf("ret expect 1,actual %d\n",ret);
printf("top expect a,actual %c\n",value);
MinStackPop(&s);
ret=MinStackTop(&s,&value);
printf("ret expect 1,actual %d\n",ret);
printf("top expect b,actual %c\n",value);
}
使用两个栈实现一个队列
思路:定义两个栈,一个栈做输入用,一个栈做输出用,入栈时在输入这个栈里入栈,出栈与取栈顶元素都从输出这个栈里取。
//使用两个栈实现一个队列
typedef struct Queby2stack
{
SeqStack input;
SeqStack output;
}Queby2stack;
void Queueby2stackPush(Queby2stack* q,StackType value)
{
if(q==NULL)
{
return;//非法输入
}
StackType top;
while(q->output.size!=0)
{
SeqStackTop(&q->output,&top);
SeqStackPop(&q->output);
SeqStackPush(&q->input,top);
}
SeqStackPush(&q->input,value);
while(q->input.size!=0)
{
SeqStackTop(&q->input,&top);
SeqStackPop(&q->input);
SeqStackPush(&q->output,top);
}
}
void Queby2stackPop(Queby2stack* q)
{
if(q==NULL)
{
return;
}
if(q->output.size==0)
{
return;
}
SeqStackPop(&q->output);
}
int Queby2stackTop(Queby2stack* q,StackType* value)
{
if(q==NULL)
{
return 0;
}
if(q->output.size==0)
{
return 0;
}
SeqStackTop(&q->output,value);
return 1;
}
void TestQueby2stack()
{
Queby2stack q;
StackType value;
SeqStackInit(&q.input);
SeqStackInit(&q.output);
Queueby2stackPush(&q,'a');
Queueby2stackPush(&q,'b');
Queueby2stackPush(&q,'c');
Queueby2stackPush(&q,'d');
Queby2stackPrint(&q,"入队列");
Queby2stackTop(&q,&value);
printf("top expect a,actual %c\n",value);
Queby2stackPop(&q);
Queby2stackPop(&q);
Queby2stackPrint(&q,"出队列");
Queby2stackTop(&q,&value);
printf("top expect c,actual %c\n",value);
}
使用两个队列实现一个栈
思路:这个题目相比于两个栈实现一个队列要复杂一些,两个栈都有既定的目标,一个做输入一个作输出。但是这两个队列没有特殊的区别。两个队列都做输出,也都做输入。画一张图来说明。
首先两个空队列,并且将元素入队列至其中一个队列中,因为我们是要实现一个栈,所以先进后出,所以出栈时应该要先出e,但是由于队列的结构限制,我们现在出队列只能出a,所以这时借助第二个队列来做一个“桥梁”。
将队列1中前几个元素都入队列至第二个队列中,此时队列1中只有e一个元素,此时再将它出队列,就能达到出栈的效果。
大致的过程就是这样,这种结构在做出栈入栈取栈顶元素时,要做的最重要的一件事是判断在该时刻哪一个队列是非空的,就对哪一个队列做入栈操作,出栈操作则要借助第二个队列。
//用两个队列实现一个栈
typedef struct Stackby2que
{
SeqQueue que1;
SeqQueue que2;
}Stackby2que;
void Stackby2quePush(Stackby2que* s,SeqQueType value)
{
if(s==NULL)
{
return;
}
if(s->que1.size!=0)
{
SeqQueuePush(&s->que1,value);
}
else
{
SeqQueuePush(&s->que2,value);
}
}
void Stackby2quePop(Stackby2que* s)
{
if(s==NULL)
{
return;
}
if(s->que1.size==0&&s->que2.size==0)
{
return;
}
if(s->que1.size!=0)
{
SeqQueType top;
while(s->que1.size!=1)
{
SeqQueueTop(&s->que1,&top);
SeqQueuePop(&s->que1);
SeqQueuePush(&s->que2,top);
}
SeqQueuePop(&s->que1);
}
else if(s->que2.size!=0)
{
SeqQueType top;
while(s->que2.size!=1)
{
SeqQueueTop(&s->que2,&top);
SeqQueuePop(&s->que2);
SeqQueuePush(&s->que1,top);
}
SeqQueuePop(&s->que2);
}
}
int Stackby2queTop(Stackby2que* s,SeqQueType* value)
{
if(s==NULL||value==NULL)
{
return 0;
}
if(s->que1.size==0&&s->que2.size==0)
{
return 0;
}
if(s->que1.size!=0)
{
while(1)
{
SeqQueueTop(&s->que1,value);
SeqQueuePush(&s->que2,*value);
SeqQueuePop(&s->que1);
if(s->que1.size==0)
{
return 1;
}
}
}
else if(s->que2.size!=0)
{
while(1)
{
SeqQueueTop(&s->que2,value);
SeqQueuePush(&s->que1,*value);
SeqQueuePop(&s->que2);
if(s->que2.size==0)
{
return 1;
}
}
}
return 0;
}
/////////////////////////////////////////////
//测试
////////////////////////////////////////////
void Stackby2quePrint(Stackby2que* s,const char* msg)
{
printf("%s\n",msg);
if(s->que1.size!=0)
{
size_t i=s->que1.head;
for(;i!=s->que1.tail;i++)
{
if(i>=MaxSize)
{
i=0;
}
printf("[%c] ",s->que1.data[i]);
}
printf("\n");
}
else if(s->que2.size!=0)
{
size_t i=s->que2.head;
for(;i!=s->que2.tail;i++)
{
if(i>=MaxSize)
{
i=0;
}
printf("[%c] ",s->que2.data[i]);
}
printf("\n");
}
}
void TestStackby2que()
{
Stackby2que s;
SeqQueType value;
SeqQueueInit(&s.que1);
SeqQueueInit(&s.que2);
Stackby2quePush(&s,'a');
Stackby2quePush(&s,'b');
Stackby2quePush(&s,'c');
Stackby2quePush(&s,'d');
Stackby2quePrint(&s,"入栈");
Stackby2queTop(&s,&value);
printf("top expect d,actual %c\n",value);
Stackby2quePop(&s);
Stackby2quePrint(&s,"出栈");
Stackby2quePop(&s);
Stackby2quePrint(&s,"出栈");
Stackby2queTop(&s,&value);
printf("top expect b,actual %c\n",value);
}
元素出栈入栈的合法性
这道题的意思是指,如果入栈的序列(1,2,3,4,5),出栈序列为(4,5,3,2,1)是否合法。
首先有两个序列,先将入栈序列从第一个开始入栈,入栈一个之后取栈顶元素,与第二个序列开始比较,如果不相等,就继续入栈,如果想等,就将该元素出栈,在取当前栈顶元素与该序列的下一个元素比较,以此类推,直到第二个序列全部都比较完毕了,说明此时成立。如果第一个序列全部入完,但是此时第二个序列还没有比较完,那么就不成立。
int StackCorrect(SeqStack* stack,char* str1,char *str2,int len)
{
if(stack==NULL||str1==NULL||str2==NULL)
{
return 0;
}
int i=0;
for(;i<len;i++)
{
//入栈一个元素,取栈顶元素与比较序列的元素比较
StackType top;
SeqStackPush(stack,*str1);
SeqStackTop(stack,&top);
while(top==*str2)
{
//如果栈顶元素与比较序列相等,就出栈,然后比较下一个
SeqStackPop(stack);
SeqStackTop(stack,&top);
str2++;
}
str1++;
}
if(*str2=='\0')
{
return 1;
}
return 0;
}
void TestStackCorrect()
{
SeqStack stack;
SeqStackInit(&stack);
char str1[]="abcde";
char str2[]="bcdea";
char str3[]="ceabd";
int len=strlen(str1);
int ret=StackCorrect(&stack,str1,str2,len);
printf("ret expect 1,actual %d\n",ret);
ret=StackCorrect(&stack,str1,str3,len);
printf("ret expect 0,actual %d\n",ret);
}
用一个数组实现两个栈
我们可以用一个数组的两端模拟两个栈顶。一个栈顶元素是top1,一个栈顶元素是top2。这样就实现了一个数组中同时存在两个栈。如下图所示。
一个栈的区间是:[0,top1)
一个栈的区间是:(top2,MAX_SIZE]
//用一个数组实现两个栈
//[0,top1)
//(top2,MAX_SIZE]
#define MAX_SIZE 100
typedef char ShareStackType;
typedef struct ShareStack
{
ShareStackType data[MAX_SIZE];
size_t top1;
size_t top2;
}ShareStack;
void ShareStackInit(ShareStack* stack)
{
if(stack==NULL)
{
return;
}
stack->top1=0;
stack->top2=MAX_SIZE;
}
void ShareStackPush1(ShareStack* stack,ShareStackType value)
{
if(stack==NULL)
{
return;
}
if(stack->top1==stack->top2)
{
return;
}
stack->data[stack->top1++]=value;
}
void ShareStackPush2(ShareStack* stack,ShareStackType value)
{
if(stack==NULL)
{
return;
}
if(stack->top1==stack->top2)
{
return;
}
stack->data[stack->top2--]=value;
}
void ShareStackpPop1(ShareStack* stack)
{
if(stack==NULL)
{
return;
}
stack->top1--;
}
void ShareStackpPop2(ShareStack* stack)
{
if(stack==NULL)
{
return;
}
stack->top2++;
}
int ShareStackTop1(ShareStack* stack,ShareStackType* value)
{
if(stack==NULL)
{
return 0;
}
if(stack->top1==stack->top2)
{
return 0;
}
*value=stack->data[stack->top1-1];
return 1;
}
int ShareStackTop2(ShareStack* stack,ShareStackType* value)
{
if(stack==NULL)
{
return 0;
}
if(stack->top1==stack->top2)
{
return 0;
}
*value=stack->data[stack->top2+1];
return 1;
}