- 实现一个栈,要求实现Push(入栈)、Pop(出栈)、Min(返回最小值)的时间复杂度为O(1)
代码实现:
我们还是要基于栈的基本操作的实现来编写这个代码。一个元素插入两次,一次表示入栈元素value,一次表示当前栈中的最小值min。需要注意的是,在入栈时,应当先入value,再入min。出栈时,每次出栈两个元素。
seqstack.h:
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<stddef.h>
typedef char SeqStackType;
typedef struct MinStack{
SeqStack stack;
}MinStack;
void MinStackPush(MinStack* min_stack,SeqStackType value);//入栈
void MinStackPop(MinStack* min_stack)//出栈
int MinStackTop(MinStack* min_stack,SeqStackType* value);//取栈顶元素
minstack.c:
#include "seqstack.h"
void MinStackPush(MinStack* min_stack,SeqStackType value){
if(min_stack == NULL)
return;
SeqStackType min = value;
SeqStackType top;
int ret = GetTop(&min_stack->stack,&top);
if(ret != 0){
min = top < value ? top : value;
}
SeqStackPush(&min_stack->stack,value);
SeqStackPush(&min_stack->stack,min);
return;
}
void MinStackPop(MinStack* min_stack){
if(min_stack == NULL)
return;
SeqStackPop(&min_stack->stack);
SeqStackPop(&min_stack->stack);
}
int MinStackTop(MinStack* min_stack,SeqStackType* value){
if(min_stack == NULL || value == NULL)
return 0;
return GetTop(&min_stack->stack,value);
}
#include "seqstack.h"
void testMinStack(){
MinStack s;
SeqStackType 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);
}
int main(){
testMinStack();
return 0;
}
结果演示:
- 使用两个栈实现一个队列
定义两个栈,一个作为输入,一个作为输出。
上面这张图为入队列时的操作示意图。
上面这张图为出队列时的操作示意图。
上面这张图为取栈顶元素的操作示意图。
queby2stack.c:
typedef struct QueBy2Stack{
SeqStack input;
SeqStack output;
}QueBy2Stack;
void QueBy2StackInit(QueBy2Stack* q){
if(q == NULL)
return;
//input用于入队列的场景
//output用于出队列和取队首元素的场景
SeqStackInit(&q->input);
SeqStackInit(&q->output);
}
void QueBy2StackPush(QueBy2Stack* q,SeqStackType value){
if(q == NULL)
return;
while(1){
SeqStackType top;
//先将所有output中的元素放到input中
int ret = GetTop(&q->output,&top);
if(ret == 0)
break;
SeqStackPop(&q->output);
SeqStackPush(&q->input,top);
}
//把新元素value插入到input中
SeqStackPush(&q->input,value);
return;
}
void QueBy2StackPop(QueBy2Stack* q){
if(q == NULL)
return;
//把所有input中的元素放到output中
while(1){
SeqStackType top;
int ret = GetTop(&q->input,&top);
if(ret == 0)
break;
SeqStackPop(&q->input);
SeqStackPush(&q->output,top);
}
//将output的栈顶元素出栈
SeqStackPop(&q->output);
}
int QueBy2StackFront(QueBy2Stack* q,SeqStackType* value){
if(q == NULL || value == NULL)
return 0;
//将所有input中的元素放到output中
while(1){
SeqStackType top;
int ret = GetTop(&q->input,&top);
if(ret == 0)
break;
SeqStackPop(&q->input);
SeqStackPush(&q->output,top);
}
return GetTop(&q->output,value);
}
test.c:
#include "seqstack.h"
void TestQueBy2Stack(){
QueBy2Stack q;
SeqStackType value;
QueBy2StackInit(&q);
QueBy2StackPush(&q,'a');
QueBy2StackPush(&q,'b');
QueBy2StackPush(&q,'c');
QueBy2StackPush(&q,'d');
int ret = QueBy2StackFront(&q,&value);
printf("ret expect 1,actual %d\n",ret);
printf("top except a,actual %c\n",value);
QueBy2StackPop(&q);
ret = QueBy2StackFront(&q,&value);
printf("ret expect 1,actual %d\n",ret);
printf("top except b,actual %c\n",value);
QueBy2StackPop(&q);
ret = QueBy2StackFront(&q,&value);
printf("ret expect 1,actual %d\n",ret);
printf("top except c,actual %c\n",value);
QueBy2StackPop(&q);
ret = QueBy2StackFront(&q,&value);
printf("ret expect 1,actual %d\n",ret);
printf("top except c,actual %c\n",value);
QueBy2StackPop(&q);
ret = QueBy2StackFront(&q,&value);
printf("ret expect 0,actual %d\n",ret);
}
int main(){
TestQueBy2Stack();
return 0;
}
结果演示:
- 使用两个队列实现一个栈
这里我们可以定义两个空队列,将所有元素依次入队列到其中一个队列中。栈要求后进先出,所以在进行入栈操作时,在非空的队列中进行push操作即可。
如上图所示,在进行出栈操作时,我们要先依次将非空队列from中的元素放到另外一个空队列to中,直至from中只剩下一个元素,然后进行pop操作即可。
上图为取栈顶元素的操作示意图。
stackbu2que.c:
typedef struct StackBy2Queue{
SeqQueue queue1;
SeqQueue queue2;
}StackBy2Queue;
void StackBy2QueueInit(StackBy2Queue* stack){
if(stack == NULL)
return;
SeqQueueInit(&stack->queue1);
SeqQueueInit(&stack->queue2);
}
void StackBy2QueuePush(StackBy2Queue* stack,SeqQueueType value){
if(stack == NULL)
return;
//取两个队列中非空的元素进行插入
SeqQueue* input = stack->queue1.size!=0 ? &stack->queue1 : &stack->queue2;
SeqQueuePush(input,value);
}
void StackBy2QueuePop(StackBy2Queue* stack){
if(stack == NULL)
return;
//若为空栈
if(stack->queue1.size == 0 && stack->queue2.size == 0)
return;
//先弄清楚谁往谁里面放元素
SeqQueue* from = NULL;
SeqQueue* to =NULL;
if(stack->queue1.size > 0){
from = &stack->queue1;
to = &stack->queue2;
}
else{
from = &stack->queue2;
to = &stack->queue1;
}
//把from中的元素放到to中
//并且一直放,直至from中只剩一个元素
while(1){
if(from->size == 1)
//此时from中只剩下一个元素,此时from中的队首元素就是栈顶元素
break;
SeqQueueType value;
SeqQueueFront(from,&value);
SeqQueuePop(from);
SeqQueuePush(to,value);
}
//把最后一个元素删除
SeqQueuePop(from);
return;
}
int StackBy2QueueTop(StackBy2Queue* stack,SeqQueueType* output_value){
if(stack == NULL || output_value == NULL)
return 0;
if(stack->queue1.size == 0 && stack->queue2.size == 0)
return 0;
//先弄清楚谁往谁里面放元素
SeqQueue* from = NULL;
SeqQueue* to =NULL;
if(stack->queue1.size > 0){
from = &stack->queue1;
to = &stack->queue2;
}
else{
from = &stack->queue2;
to = &stack->queue1;
}
//把from中的元素放到to中
while(1){
if(from->size == 0)
break;
SeqQueueFront(from,output_value);
SeqQueuePop(from);
SeqQueuePush(to,*output_value);
}
return 1;
}
#include "seqqueue.h"
#define PRINT_HEADER printf("\n============%s============\n",__FUNCTION__)
void TestStack(){
PRINT_HEADER;
StackBy2Queue stack;
StackBy2QueueInit(&stack);
StackBy2QueuePush(&stack,'a');
StackBy2QueuePush(&stack,'b');
StackBy2QueuePush(&stack,'c');
StackBy2QueuePush(&stack,'d');
SeqQueueType value;
int ret = StackBy2QueueTop(&stack,&value);
printf("ret expect 1,actual %d\n",ret);
printf("value expect d,actual %c\n",value);
StackBy2QueuePop(&stack);
ret = StackBy2QueueTop(&stack,&value);
printf("ret expect 1,actual %d\n",ret);
printf("value expect c,actual %c\n",value);
StackBy2QueuePop(&stack);
ret = StackBy2QueueTop(&stack,&value);
printf("ret expect 1,actual %d\n",ret);
printf("value expect b,actual %c\n",value);
StackBy2QueuePop(&stack);
ret = StackBy2QueueTop(&stack,&value);
printf("ret expect 1,actual %d\n",ret);
printf("value expect a,actual %c\n",value);
StackBy2QueuePop(&stack);
ret = StackBy2QueueTop(&stack,&value);
printf("ret expect 0,actual %d\n",ret);
return;
}
int main(){
TestStack();
return 0;
}
结果演示:
- 元素入栈、出栈顺序的合法性
stackorder.c:
#include "seqstack.h"
#include<stddef.h>
int StackOrder(char input[],size_t input_size,char output[],size_t output_size){
SeqStack stack;
SeqStackInit(&stack);
//1.循环的将input中的元素入栈
size_t i = 0;
int output_index = 0;
for(;i < input_size;i++){
SeqStackPush(&stack,input[i]);
char top;
int ret = GetTop(&stack,&top);
if(ret == 0)
//栈已空,准备进行最终判断
break;
//2.取栈顶元素与output_index指向的元素作比较
while(1){
//3.若不相等,继续循环取下一个input中的元素入栈
//4.若相等
//a)将output_index往后移
//b)将栈顶元素出栈
//c)循环的比较栈顶元素与output_index指向的元素的值
if(output_index >= output_size){
//output序列已经遍历完毕,需要进行最终判断
break;
}
if(top != output[output_index]){
break;
}
++output_index;
SeqStackPop(&stack);
}
}
//5.若最终栈为空且output_index指向output数组中的最后一个元素的下一个元素,则认为可以变换得到
if(stack.size == 0 && output_index == output_size){
return 1;
}
//否则无法变换得到
return 0;
}
test.c:
#include "seqstack.h"
void TestStackOrder(){
SeqStack stack;
SeqStackInit(&stack);
char input[] = "abcde";
char output1[] = "decba";
char output2[] = "deabc";
int size = sizeof(input)/sizeof(input[0]);
int ret = StackOrder(input,size,output1,size);
printf("ret expect 1,actual %d\n",ret);
ret = StackOrder(input,size,output2,size);
printf("ret expect 0,actual %d\n",ret);
return;
}
int main(){
TestStackOrder();
return 0;
}
结果演示:
- 一个数组实现两个栈(共享栈)
sharedstack.h:
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<stddef.h>
#define MaxSize 100
typedef int SharedStackType;
typedef struct SharedStack{
int arr[MaxSize];
int top1;
int top2;
}SharedStack;
sharedstack.c:
#include "sharedstack.h"
void SharedStackInit(SharedStack* s){
if(s == NULL)
return;
s->top1 = 0;
s->top2 = MaxSize;
}
void SharedStackPush(SharedStack* s,SharedStackType value,SharedStackType which){
if(s == NULL)
return;
if(s->top1 >= s->top2)
//栈满
return;
if(which != 1 && which != 2)
//既不在栈1也不在栈2
//非法输入
return;
if(which == 1){
s->arr[s->top1++] = value;
}
else{
s->arr[--s->top2] = value;
}
return;
}
int IsEmpty(SharedStack* s,SharedStackType which){
if(s == NULL)
return 0;
if(which != 1 && which != 2)
return 0;
if(which == 1){
return s->top1==0 ? 1:0;
}
else{
return s->top2==MaxSize? 1:0;
}
return 0;
}
void SharedStackPop(SharedStack* s,SharedStackType which){
if(s == NULL)
return;
if(IsEmpty(s,which)){
//栈为空
return;
}
if(which != 1 && which != 2){
return;
}
if(which == 1){
s->top1--;
}
else{
s->top2++;
}
return;
}
int SharedStackTop(SharedStack* s,SharedStackType which){
if(s == NULL)
return 0;
if(IsEmpty(s,which))
return 0;
if(which == 1){
return s->arr[s->top1-1];
}
else{
return s->arr[s->top2];
}
return 0;
}
test.c:
#include"sharedstack.h"
void TestSharedStack(){
SharedStack s;
SharedStackInit(&s);
SharedStackPush(&s,1,1);
SharedStackPush(&s,2,1);
SharedStackPush(&s,3,1);
SharedStackPush(&s,4,1);
int ret1 = SharedStackTop(&s,1);
printf("ret1 expect 4,actual %d\n",ret1);
SharedStackPop(&s,1);
SharedStackPop(&s,1);
ret1 = SharedStackTop(&s,1);
printf("ret1 expect 2,actual %d\n",ret1);
SharedStackPush(&s,5,2);
SharedStackPush(&s,6,2);
SharedStackPush(&s,7,2);
SharedStackPush(&s,8,2);
int ret2 = SharedStackTop(&s,2);
printf("ret2 expect 8,actual %d\n",ret2);
SharedStackPop(&s,2);
SharedStackPop(&s,2);
ret2 = SharedStackTop(&s,2);
printf("ret2 expect 6,actual %d\n",ret2);
}
int main(){
TestSharedStack();
}
结果演示: