1.实现一个最小栈,每次取得都是栈里面的最小值,时间复杂度为O(1)
思路:每次入栈两个元素,一个存当前值,一个存当前栈的最小值,先将当前值入栈,再将最小值入栈,出栈时也一次出两个。如图所示:
代码如下:
#include"seqstack.h"
#include<stdio.h>
typedef struct MinStack
{
SeqStack stack;
}MinStack;
void MinStackInit(MinStack* min_stack)
{
if(min_stack == NULL)
{
return;
}
SeqStackInit(&min_stack->stack);
}
void MinStackPush(MinStack* min_stack,SeqStackType value)
{
if(min_stack == NULL)
{
return;//非法输入
}
SeqStackType min = value;
//取栈顶元素
SeqStackType top;
int ret = SeqStackTop(&min_stack->stack,&top);
if(ret != 0)
{
//将栈顶元素和value值进行比较,将小指赋给min
if(top > value)
{
min = value;
}
min = top;
}
//一次入两个元素,先插value,后插min,才能保证栈顶元素是最小的
SeqStackPush(&min_stack->stack,value);
SeqStackPush(&min_stack->stack,min);
}
void MinStackPop(MinStack* min_stack)
{
if(min_stack == NULL)
{
return;//非法输入
}
if(min_stack->stack.size == 0)
{
return;//空栈
}
//连续出栈两个元素
SeqStackPop(&min_stack->stack);
SeqStackPop(&min_stack->stack);
return;
}
int MinStackTop(MinStack* min_stack,SeqStackType* value)
{
if(min_stack == NULL)
{
return 0;//非法输入
}
SeqStackTop(&min_stack->stack,value);
}
///////////////////////////////////////
/////////以下是测试代码///////////////
//////////////////////////////////////
#define TEST_HEADER printf("\n==============%s============\n",__FUNCTION__)
void TestMinStack()
{
TEST_HEADER;
MinStack min_stack;
MinStackInit(&min_stack);
MinStackPush(&min_stack,'a');
MinStackPush(&min_stack,'b');
MinStackPush(&min_stack,'c');
MinStackPush(&min_stack,'d');
SeqStackType value;
int ret = MinStackTop(&min_stack,&value);
printf("ret expected 1,actual %d\n",ret);
printf("value expected a,actual %c\n",value);
MinStackPop(&min_stack);
MinStackPop(&min_stack);
ret = MinStackTop(&min_stack,&value);
printf("ret expected 1,actual %d\n",ret);
printf("value1 expected a,actual %c\n",value);
}
int main()
{
TestMinStack();
printf("\n");
return 0;
}
2.使用两个栈实现一个队列
思路:一个栈实现入队列的场景,一个栈实现出队列和取队首元素
例如上图,按照队列”先进先出”规则,先将a b c d按顺序依次压入input栈,然后取input栈栈顶元素按顺序依次出栈再压入output栈,最后在output栈依次出栈栈顶元素,就达到预期效果。
代码如下:
#include<stdio.h>
#include"seqstack.h"
typedef struct QueueBy2Stack
{
SeqStack input;
SeqStack output;
}QueueBy2Stack;
void QueueInit(QueueBy2Stack* queue)
{
if(queue == NULL)
{
return;//非法输入
}
SeqStackInit(&queue->input);
SeqStackInit(&queue->output);
}
void QueuePush(QueueBy2Stack* q,SeqStackType value)
{
if(q == NULL)
{
return;//非法输入
}
//先把所有output的元素出栈然后按顺序入栈到input里
while(1)
{
SeqStackType top;
int ret = SeqStackTop(&q->output,&top);
if(ret == 0)
{
break;
}
SeqStackPush(&q->input,top);
SeqStackPop(&q->output);
}
//把新元素value插入到input中
SeqStackPush(&q->input,value);
return;
}
void QueuePop(QueueBy2Stack* q)
{
if(q == NULL)
{
return;//非法输入
}
//先把input里所有元素倒腾到output里
while(1)
{
SeqStackType top;
int ret = SeqStackTop(&q->input,&top);
if(ret == 0)
{
break;
}
SeqStackPush(&q->output,top);
SeqStackPop(&q->input);
}
SeqStackPop(&q->output);
return;
}
int QueueFront(QueueBy2Stack* q,SeqStackType* value)
{
if(q == NULL|| value == NULL)
{
return 0;;//非法输入
}
//把input里的所有元素倒腾到output里
while(1)
{
SeqStackType top;
int ret = SeqStackTop(&q->input,&top);
if(ret == 0)
{
break;
}
SeqStackPush(&q->output,top);
SeqStackPop(&q->input);
}
return SeqStackTop(&q->output,value);
}
////////////////////////////////////////
//////////以下是测试代码///////////////
///////////////////////////////////////
#if 1
#include<stdio.h>
#define TEST_HEADER printf("\n=================%s================\n",__FUNCTION__)
void TestQueue()
{
TEST_HEADER;
QueueBy2Stack queue;
QueueInit(&queue);
QueuePush(&queue,'a');
QueuePush(&queue,'b');
QueuePush(&queue,'c');
QueuePush(&queue,'d');
SeqStackType value;
int ret = QueueFront(&queue,&value);
printf("ret expected 1,actual %d\n",ret);
printf("value expected a,acatual %c\n",value);
QueuePop(&queue);
ret = QueueFront(&queue,&value);
printf("ret expected 1,actual %d\n",ret);
printf("value expected b,acatual %c\n",value);
QueuePop(&queue);
ret = QueueFront(&queue,&value);
printf("ret expected 1,actual %d\n",ret);
printf("value expected c,acatual %c\n",value);
QueuePop(&queue);
ret = QueueFront(&queue,&value);
printf("ret expected 1,actual %d\n",ret);
printf("value expected d,acatual %c\n",value);
QueuePop(&queue);
ret = QueueFront(&queue,&value);
printf("ret expected 0,actual %d\n",ret);
}
int main()
{
TestQueue();
printf("\n");
return 0;
}
#endif
3.使用两个队列实现一个栈
思路:入栈时将元素插入到不为空的队列里,出栈时将不为空的队列里只留下最后一个元素,将其余元素出队列然后插入到另一个空队列里。需要注意的是要搞清楚将元素从哪个队列倒腾到哪个队列。
代码如下:
#include<stdio.h>
#include"seqqueue.h"
typedef struct StackBy2Queue
{
SeqQueue queue1;
SeqQueue queue2;
}StackBy2Queue;
void StackInit(StackBy2Queue* stack)
{
if(stack == NULL)
{
return;//非法输入
}
SeqQueueInit(&stack->queue1);
SeqQueueInit(&stack->queue2);
}
void StackPush(StackBy2Queue* stack,SeqQueueType value)
{
if(stack == NULL)
{
return;//非法输入
}
SeqQueue* input;
//先判断哪个队列不为空,然后将元素插入到那个队列里
if(stack->queue1.size != 0)
{
input = &stack->queue1;
}
input = &stack->queue2;
SeqQueuePush(input,value);
}
void StackPop(StackBy2Queue* stack)
{
if(stack == NULL)
{
return;//非法输入
}
//如果是空栈,直接返回
if(stack->queue1.size == 0 && stack->queue2.size == 0)
{
return;
}
//先判断哪个队列为空,不为空队列为from,空队列为to
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)
{
break;
}
SeqQueueType value;
int ret = SeqQueueFront(from,&value);
SeqQueuePop(from);
SeqQueuePush(to,value);
}
SeqQueuePop(from);
}
int StackFront(StackBy2Queue* stack,SeqQueueType* value)
{
if(stack == NULL)
{
return 0;//非法输入
}
//如果是空栈,直接返回
if(stack->queue1.size == 0 && stack->queue2.size == 0)
{
return 0;
}
//先判断哪个队列为空,不为空队列为from,空队列为to
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)
{
break;
}
SeqQueueFront(from,value);
SeqQueuePop(from);
SeqQueuePush(to,*value);
}
//将剩下的最后一个元素取出来赋给value
SeqQueueFront(from,value);
SeqQueuePop(from);
SeqQueuePush(to,*value);
return 1;
}
//以下是测试代码///
//
#if 1
#include<stdio.h>
#define TEST_HEADER printf("\n====================%s=======================\n",__FUNCTION__)
void TestStack()
{
TEST_HEADER;
StackBy2Queue stack;
StackInit(&stack);
StackPush(&stack,'a');
StackPush(&stack,'b');
StackPush(&stack,'c');
StackPush(&stack,'d');
SeqQueueType value;
int ret = StackFront(&stack,&value);
printf("ret expected 1,actual %d\n",ret);
printf("value expected d,actual %c\n",value);
StackPop(&stack);
ret = StackFront(&stack,&value);
printf("ret expected 1,actual %d\n",ret);
printf("value expected c,actual %c\n",value);
StackPop(&stack);
ret = StackFront(&stack,&value);
printf("ret expected 1,actual %d\n",ret);
printf("value expected b,actual %c\n",value);
StackPop(&stack);
ret = StackFront(&stack,&value);
printf("ret expected 1,actual %d\n",ret);
printf("value expected a,actual %c\n",value);
StackPop(&stack);
ret = StackFront(&stack,&value);
printf("ret expected 0,actual %d\n",ret);
}
int main()
{
TestStack();
printf("\n");
return 0;
}
#endif
4.判断一个入栈序列是否可以通过入栈、出栈操作得到出栈序列,如,入栈序列(input)为(a,b,c,d,e),出栈序列(output)为(d,e,c,b,a)
思路:定义两重循环,第一重,循环的遍历input,然后将input中的元素入栈;第二重,取栈顶元素,如果栈顶元素的值和oi指向的值相同,循环的出栈,并且再次比较栈顶元素和oi移进之后的值。
代码如下:
#include<stdio.h>
#include<stddef.h>
#include"seqstack.h"
#include<string.h>
//返回1表示能变换成功
//返回0表示不能变换成功
int StackOrder(char input[],size_t input_size,char output[],size_t output_size)
{
SeqStack stack;
SeqStackInit(&stack);
size_t i = 0;
size_t output_index = 0;
char top;
for( ;i < input_size;i++)
{
//1.循环的把input入栈
SeqStackPush(&stack,input[i]);
int ret = SeqStackTop(&stack,&top);
//2.取栈顶元素,和output_index指向的元素进行比较
while(1)
{
SeqStackTop(&stack,&top);
if(output_index >= output_size)
{
break;//output_index走到output数组的最后一个
}
//3.如果不相等,继续循环取下一个input元素入栈
if(top != output[output_index])
{
break;
}
//4.如果相等
// a)移进output_index
// b)把栈顶元素出栈
// c)再循环的比较栈顶元素和output_index指向的值
++output_index;
SeqStackPop(&stack);
}
if(ret == 0)
{
break;//栈为空进行最终审判
}
}
//5.如果最后栈为空并且output_index指向output数组中的最后一个元素的下一个元素,
//就认为output可以通过input变换得到
//6.否则则不能通过变换得到
if(stack.size == 0 && output_index == output_size)
{
return 1;
}
return 0;
}
////////////////////////////////////
//////////以下为测试代码////////////
///////////////////////////////////
#if 1
#include<stdio.h>
#define TEST_HEADER printf("\n====================%s======================\n",__FUNCTION__)
void TestOrder()
{
TEST_HEADER;
char input[6] = "abcde";
char output[6] = "decba";
size_t input_size = strlen(input);
size_t output_size = strlen(output);
int ret = StackOrder(input,input_size,output,output_size);
printf("ret expected 1,actual %d\n",ret);
if(ret == 1)
{
printf("output 可以通过input变换得到\n");
}
else
{
printf("output 不能通过input变换得到\n");
}
}
int main()
{
TestOrder();
printf("\n");
return 0;
}
#endif
5.一个数组实现两个栈(共享栈)
我们做一种约定:第一个栈区间为[0,top1),第二个栈区间为[top2,max_size),当top1 == top2表示栈满了。
代码如下:
#include<stdio.h>
#include<stddef.h>
#define SharedStackMixSize 1000
typedef char SharedStackType;
//[0,top1)表示第一个栈
//[top2,SharedSatckMixSize)表示第二个栈
typedef struct SharedStack
{
SharedStackType data[SharedStackMixSize];
size_t top1;
size_t top2;
}SharedStack;
void SharedStackInit(SharedStack* stack)
{
if(stack == NULL)
{
return;//非法输入
}
stack->top1 = 0;
stack->top2 = SharedStackMixSize;
return;
}
void SharedStackPush1(SharedStack* stack,SharedStackType value)
{
if(stack == NULL)
{
return;//非法输入
}
if(stack->top1 >= stack->top2)
{
return;//栈已满,不能再插入元素
}
stack->data[stack->top1++] = value;//将元素插入到top1指向的位置,再将top1指向下一个位置
return;
}
void SharedStackPush2(SharedStack* stack,SharedStackType value)
{
if(stack == NULL)
{
return;//非法输入
}
if(stack->top1 >= stack->top2)
{
return;//栈已满,不能再插入元素
}
stack->data[--stack->top2] = value;//先将top2减一,再将元素插入到top2指向的位置
return;
}
int SharedStackTop1(SharedStack* stack,SharedStackType* value)
{
if(stack == NULL)
{
return 0;//非法输入
}
if(stack->top1 == 0)
{
return 0;//空栈
}
*value = stack->data[stack->top1-1];//top1的前一个位置为有效值,将其赋给value
return 1;
}
int SharedStackTop2(SharedStack* stack,SharedStackType* value)
{
if(stack == NULL)
{
return 0;//非法输入
}
if(stack->top2 == SharedStackMixSize)
{
return 0;//空栈
}
*value = stack->data[stack->top2];//top2指向的位置就是有效值,将其赋给value
return 1;
}
void SharedStackPop1(SharedStack* stack)
{
if(stack == NULL)
{
return;//非法输入
}
if(stack->top1 == 0)
{
return;//空栈
}
--stack->top1;
return;
}
void SharedStackPop2(SharedStack* stack)
{
if(stack == NULL)
{
return;//非法输入
}
if(stack->top2 == SharedStackMixSize)
{
return;//空栈
}
++stack->top2;
return;
}
/
///以下是测试代码///
///
#include<stdio.h>
#if 1
#define TEST_HEADER printf("\n=======================%s====================\n",__FUNCTION__)
void TestInit()
{
TEST_HEADER;
SharedStack stack;
SharedStackInit(&stack);
}
void Test1()
{
TEST_HEADER;
SharedStack stack;
SharedStackInit(&stack);
SharedStackPush1(&stack,'a');
SharedStackPush1(&stack,'b');
SharedStackPush1(&stack,'c');
SharedStackPush1(&stack,'d');
SharedStackType value;
int ret = SharedStackTop1(&stack,&value);
printf("ret expected 1,actual %d\n",ret);
printf("value expected d,actual %c\n",value);
SharedStackPop1(&stack);
SharedStackPop1(&stack);
ret = SharedStackTop1(&stack,&value);
printf("ret expected 1,actual %d\n",ret);
printf("value expected b,actual %c\n",value);
SharedStackPop1(&stack);
SharedStackPop1(&stack);
ret = SharedStackTop1(&stack,&value);
printf("ret expected 0,actual %d\n",ret);
}
void Test2()
{
TEST_HEADER;
SharedStack stack;
SharedStackInit(&stack);
SharedStackPush2(&stack,'a');
SharedStackPush2(&stack,'b');
SharedStackPush2(&stack,'c');
SharedStackPush2(&stack,'d');
SharedStackType value;
int ret = SharedStackTop2(&stack,&value);
printf("ret expected 1,actual %d\n",ret);
printf("value expected d,actual %c\n",value);
SharedStackPop2(&stack);
SharedStackPop2(&stack);
ret = SharedStackTop2(&stack,&value);
printf("ret expected 1,actual %d\n",ret);
printf("value expected b,actual %c\n",value);
SharedStackPop2(&stack);
SharedStackPop2(&stack);
ret = SharedStackTop2(&stack,&value);
printf("ret expected 0,actual %d\n",ret);
}
int main()
{
TestInit();
Test1();
Test2();
printf("\n");
return 0;
}
#endif